* device/lib/Makefile.in: removed comment line with model-pic16,
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
62
63 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_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
277 {
278
279   if(pcop)
280     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
281   else
282     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
283     
284 //    fprintf(stderr, "%s\n", pcop->name);
285 }
286
287 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
288 {
289
290   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
291
292 }
293
294
295 #if 1
296 #define pic16_emitcode  DEBUGpic16_emitcode
297 #else
298 /*-----------------------------------------------------------------*/
299 /* pic16_emitcode - writes the code into a file : for now it is simple    */
300 /*-----------------------------------------------------------------*/
301 void pic16_emitcode (char *inst,char *fmt, ...)
302 {
303     va_list ap;
304     char lb[INITIAL_INLINEASM];  
305     char *lbp = lb;
306
307     va_start(ap,fmt);   
308
309     if (inst && *inst) {
310         if (fmt && *fmt)
311             sprintf(lb,"%s\t",inst);
312         else
313             sprintf(lb,"%s",inst);
314         vsprintf(lb+(strlen(lb)),fmt,ap);
315     }  else
316         vsprintf(lb,fmt,ap);
317
318     while (isspace(*lbp)) lbp++;
319
320     if (lbp && *lbp) 
321         lineCurr = (lineCurr ?
322                     connectLine(lineCurr,newLineNode(lb)) :
323                     (lineHead = newLineNode(lb)));
324     lineCurr->isInline = _G.inLine;
325     lineCurr->isDebug  = _G.debugLine;
326
327 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
328
329 //    if(pic16_debug_verbose)
330 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
331
332     va_end(ap);
333 }
334 #endif
335
336
337 /*-----------------------------------------------------------------*/
338 /* pic16_emitDebuggerSymbol - associate the current code location  */
339 /*   with a debugger symbol                                        */
340 /*-----------------------------------------------------------------*/
341 void
342 pic16_emitDebuggerSymbol (char * debugSym)
343 {
344   _G.debugLine = 1;
345   pic16_emitcode (";", "%s ==.", debugSym);
346   _G.debugLine = 0;
347 }
348
349
350 /*-----------------------------------------------------------------*/
351 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
352 /*-----------------------------------------------------------------*/
353 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
354 {
355     bool r0iu = FALSE , r1iu = FALSE;
356     bool r0ou = FALSE , r1ou = FALSE;
357
358         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
359
360     /* the logic: if r0 & r1 used in the instruction
361     then we are in trouble otherwise */
362
363     /* first check if r0 & r1 are used by this
364     instruction, in which case we are in trouble */
365     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
366         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
367     {
368         goto endOfWorld;      
369     }
370
371     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
372     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
373
374     /* if no usage of r0 then return it */
375     if (!r0iu && !r0ou) {
376         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
377         (*aopp)->type = AOP_R0;
378         
379         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
380     }
381
382     /* if no usage of r1 then return it */
383     if (!r1iu && !r1ou) {
384         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
385         (*aopp)->type = AOP_R1;
386
387         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
388     }    
389
390     /* now we know they both have usage */
391     /* if r0 not used in this instruction */
392     if (!r0iu) {
393         /* push it if not already pushed */
394         if (!_G.r0Pushed) {
395           //pic16_emitcode ("push","%s",
396           //          pic16_regWithIdx(R0_IDX)->dname);
397             _G.r0Pushed++ ;
398         }
399         
400         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
401         (*aopp)->type = AOP_R0;
402
403         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
404     }
405
406     /* if r1 not used then */
407
408     if (!r1iu) {
409         /* push it if not already pushed */
410         if (!_G.r1Pushed) {
411           //pic16_emitcode ("push","%s",
412           //          pic16_regWithIdx(R1_IDX)->dname);
413             _G.r1Pushed++ ;
414         }
415         
416         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
417         (*aopp)->type = AOP_R1;
418         return pic16_regWithIdx(R1_IDX);
419     }
420
421 endOfWorld :
422     /* I said end of world but not quite end of world yet */
423     /* if this is a result then we can push it on the stack*/
424     if (result) {
425         (*aopp)->type = AOP_STK;    
426         return NULL;
427     }
428
429     /* other wise this is true end of the world */
430     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
431            "getFreePtr should never reach here");
432     exit(0);
433 }
434
435 /*-----------------------------------------------------------------*/
436 /* newAsmop - creates a new asmOp                                  */
437 /*-----------------------------------------------------------------*/
438 static asmop *newAsmop (short type)
439 {
440     asmop *aop;
441
442     aop = Safe_calloc(1,sizeof(asmop));
443     aop->type = type;
444     return aop;
445 }
446
447 static void genSetDPTR(int n)
448 {
449     if (!n)
450     {
451         pic16_emitcode(";", "Select standard DPTR");
452         pic16_emitcode("mov", "dps, #0x00");
453     }
454     else
455     {
456         pic16_emitcode(";", "Select alternate DPTR");
457         pic16_emitcode("mov", "dps, #0x01");
458     }
459 }
460
461 /*-----------------------------------------------------------------*/
462 /* resolveIfx - converts an iCode ifx into a form more useful for  */
463 /*              generating code                                    */
464 /*-----------------------------------------------------------------*/
465 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
466 {
467
468   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
469
470   if(!resIfx) 
471     return;
472
473
474   resIfx->condition = 1;    /* assume that the ifx is true */
475   resIfx->generated = 0;    /* indicate that the ifx has not been used */
476
477   if(!ifx) {
478     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
479
480 #if 1
481     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
482                         __FUNCTION__,__LINE__,resIfx->lbl->key);
483 #endif
484
485   } else {
486     if(IC_TRUE(ifx)) {
487       resIfx->lbl = IC_TRUE(ifx);
488     } else {
489       resIfx->lbl = IC_FALSE(ifx);
490       resIfx->condition = 0;
491     }
492
493 #if 1
494     if(IC_TRUE(ifx)) 
495       DEBUGpic16_emitcode("; ***","ifx true is non-null");
496     if(IC_FALSE(ifx)) 
497       DEBUGpic16_emitcode("; ***","ifx false is non-null");
498 #endif
499   }
500
501   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
502
503 }
504 #if 0
505 /*-----------------------------------------------------------------*/
506 /* pointerCode - returns the code for a pointer type               */
507 /*-----------------------------------------------------------------*/
508 static int pointerCode (sym_link *etype)
509 {
510
511     return PTR_TYPE(SPEC_OCLS(etype));
512
513 }
514 #endif
515
516 /*-----------------------------------------------------------------*/
517 /* aopForSym - for a true symbol                                   */
518 /*-----------------------------------------------------------------*/
519 static asmop *aopForSym (iCode *ic, operand *op, bool result)
520 {
521     symbol *sym=OP_SYMBOL(op);
522     asmop *aop;
523     memmap *space= SPEC_OCLS(sym->etype);
524
525     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
526
527 //    sym = OP_SYMBOL(op);
528
529     /* if already has one */
530     if (sym->aop) {
531             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
532         return sym->aop;
533     }
534
535     /* if symbol was initially placed onStack then we must re-place it
536      * to direct memory, since pic16 does not have a specific stack */
537     if(sym->onStack) {
538         sym->onStack = 0;
539         SPEC_OCLS( sym->etype ) = data;
540         space = data;
541     }
542     
543
544 #if 1
545     /* assign depending on the storage class */
546     /* if it is on the stack or indirectly addressable */
547     /* space we need to assign either r0 or r1 to it   */    
548     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
549
550         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
551                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
552         
553         sym->aop = aop = newAsmop(0);
554         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
555         aop->size = getSize(sym->type);
556
557         /* now assign the address of the variable to 
558         the pointer register */
559         if (aop->type != AOP_STK) {
560
561             if (sym->onStack) {
562                     if ( _G.accInUse )
563                         pic16_emitcode("push","acc");
564
565                     pic16_emitcode("mov","a,_bp");
566                     pic16_emitcode("add","a,#0x%02x",
567                              ((sym->stack < 0) ?
568                               ((char)(sym->stack - _G.nRegsSaved )) :
569                               ((char)sym->stack)) & 0xff);
570                     pic16_emitcode("mov","%s,a",
571                              aop->aopu.aop_ptr->name);
572
573                     if ( _G.accInUse )
574                         pic16_emitcode("pop","acc");
575             } else
576                 pic16_emitcode("mov","%s,#%s",
577                          aop->aopu.aop_ptr->name,
578                          sym->rname);
579             aop->paged = space->paged;
580         } else
581             aop->aopu.aop_stk = sym->stack;
582         return aop;
583     }
584 #endif
585
586     if (sym->onStack && options.stack10bit)
587     {
588         /* It's on the 10 bit stack, which is located in
589          * far data space.
590          */
591          
592       //DEBUGpic16_emitcode(";","%d",__LINE__);
593
594         if ( _G.accInUse )
595                 pic16_emitcode("push","acc");
596
597         pic16_emitcode("mov","a,_bp");
598         pic16_emitcode("add","a,#0x%02x",
599                  ((sym->stack < 0) ?
600                    ((char)(sym->stack - _G.nRegsSaved )) :
601                    ((char)sym->stack)) & 0xff);
602         
603         genSetDPTR(1);
604         pic16_emitcode ("mov","dpx1,#0x40");
605         pic16_emitcode ("mov","dph1,#0x00");
606         pic16_emitcode ("mov","dpl1, a");
607         genSetDPTR(0);
608         
609         if ( _G.accInUse )
610             pic16_emitcode("pop","acc");
611             
612         sym->aop = aop = newAsmop(AOP_DPTR2);
613         aop->size = getSize(sym->type); 
614         return aop;
615     }
616
617     //DEBUGpic16_emitcode(";","%d",__LINE__);
618     /* if in bit space */
619     if (IN_BITSPACE(space)) {
620         sym->aop = aop = newAsmop (AOP_CRY);
621         aop->aopu.aop_dir = sym->rname ;
622         aop->size = getSize(sym->type);
623         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
624         return aop;
625     }
626     /* if it is in direct space */
627     if (IN_DIRSPACE(space)) {
628         sym->aop = aop = newAsmop (AOP_DIR);
629         aop->aopu.aop_dir = sym->rname ;
630         aop->size = getSize(sym->type);
631         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
632         pic16_allocDirReg( IC_LEFT(ic) );
633         return aop;
634     }
635
636 #if 0                                                                                           // patch 14
637     /* special case for a function */
638     if (IS_FUNC(sym->type)) {   
639         sym->aop = aop = newAsmop(AOP_IMMD);    
640         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
641         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
642         strcpy(aop->aopu.aop_immd,sym->rname);
643         aop->size = FPTRSIZE; 
644         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
645         return aop;
646     }
647 #endif                                                                                          // patch 14
648
649
650     /* only remaining is far space */
651     /* in which case DPTR gets the address */
652     sym->aop = aop = newAsmop(AOP_PCODE);
653
654 /* change the next if to 1 to revert to good old immediate code */
655         if(IN_CODESPACE(space)) {
656                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
657                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
658                 PCOI(aop->aopu.pcop)->index = 0;
659         } else {
660                 /* try to allocate via direct register */
661                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
662 //              aop->size = getSize( sym->type );
663         }
664
665         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
666                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
667
668 #if 0
669         if(!pic16_allocDirReg (IC_LEFT(ic)))
670                 return NULL;
671 #endif
672
673         if(IN_DIRSPACE( space ))
674                 aop->size = PTRSIZE;
675         else if(IN_CODESPACE( space ))
676                 aop->size = FPTRSIZE;
677         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
678         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
679         else {
680                 assert( 0 );
681         }
682
683     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
684
685     /* if it is in code space */
686     if (IN_CODESPACE(space))
687         aop->code = 1;
688
689     return aop;     
690 }
691
692 /*-----------------------------------------------------------------*/
693 /* aopForRemat - rematerialzes an object                           */
694 /*-----------------------------------------------------------------*/
695 static asmop *aopForRemat (operand *op) // x symbol *sym)
696 {
697   symbol *sym = OP_SYMBOL(op);
698   iCode *ic = NULL, *oldic;
699   asmop *aop = newAsmop(AOP_PCODE);
700   int val = 0;
701   int offset = 0;
702   int viaimmd=0;
703
704
705         ic = sym->rematiCode;
706
707         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
708         
709         if(IS_OP_POINTER(op)) {
710                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
711         }
712
713         for (;;) {
714                 oldic = ic;
715
716 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
717         
718                 if (ic->op == '+') {
719                         val += (int) operandLitValue(IC_RIGHT(ic));
720                 } else if (ic->op == '-') {
721                         val -= (int) operandLitValue(IC_RIGHT(ic));
722                 } else
723                         break;
724                 
725                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
726         }
727
728         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
729
730         if(!op->isaddr)viaimmd++; else viaimmd=0;
731                 
732 /* set the following if to 1 to revert to good old immediate code */
733         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
734                 || viaimmd) {
735
736                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
737
738                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
739
740 #if 0
741                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
742 #else
743                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
744 #endif
745
746                 PCOI(aop->aopu.pcop)->index = val;
747         } else {
748                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
749
750                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
751                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
752 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
753         }
754
755
756         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
757                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
758 #if 0
759                 val, IS_PTR_CONST(operandType(op)));
760 #else
761                 val, IS_CODEPTR(operandType(op)));
762 #endif
763
764 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
765
766         pic16_allocDirReg (IC_LEFT(ic));
767
768         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
769                 aop->code = 1;
770
771   return aop;        
772 }
773
774 static int aopIdx (asmop *aop, int offset)
775 {
776   if(!aop)
777     return -1;
778
779   if(aop->type !=  AOP_REG)
780     return -2;
781         
782   return aop->aopu.aop_reg[offset]->rIdx;
783
784 }
785 /*-----------------------------------------------------------------*/
786 /* regsInCommon - two operands have some registers in common       */
787 /*-----------------------------------------------------------------*/
788 static bool regsInCommon (operand *op1, operand *op2)
789 {
790     symbol *sym1, *sym2;
791     int i;
792
793     /* if they have registers in common */
794     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
795         return FALSE ;
796
797     sym1 = OP_SYMBOL(op1);
798     sym2 = OP_SYMBOL(op2);
799
800     if (sym1->nRegs == 0 || sym2->nRegs == 0)
801         return FALSE ;
802
803     for (i = 0 ; i < sym1->nRegs ; i++) {
804         int j;
805         if (!sym1->regs[i])
806             continue ;
807
808         for (j = 0 ; j < sym2->nRegs ;j++ ) {
809             if (!sym2->regs[j])
810                 continue ;
811
812             if (sym2->regs[j] == sym1->regs[i])
813                 return TRUE ;
814         }
815     }
816
817     return FALSE ;
818 }
819
820 /*-----------------------------------------------------------------*/
821 /* operandsEqu - equivalent                                        */
822 /*-----------------------------------------------------------------*/
823 static bool operandsEqu ( operand *op1, operand *op2)
824 {
825     symbol *sym1, *sym2;
826
827     /* if they not symbols */
828     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
829         return FALSE;
830
831     sym1 = OP_SYMBOL(op1);
832     sym2 = OP_SYMBOL(op2);
833
834     /* if both are itemps & one is spilt
835        and the other is not then false */
836     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
837         sym1->isspilt != sym2->isspilt )
838         return FALSE ;
839
840     /* if they are the same */
841     if (sym1 == sym2)
842         return TRUE ;
843
844     if (strcmp(sym1->rname,sym2->rname) == 0)
845         return TRUE;
846
847
848     /* if left is a tmp & right is not */
849     if (IS_ITEMP(op1)  && 
850         !IS_ITEMP(op2) &&
851         sym1->isspilt  &&
852         (sym1->usl.spillLoc == sym2))
853         return TRUE;
854
855     if (IS_ITEMP(op2)  && 
856         !IS_ITEMP(op1) &&
857         sym2->isspilt  &&
858         sym1->level > 0 &&
859         (sym2->usl.spillLoc == sym1))
860         return TRUE ;
861
862     return FALSE ;
863 }
864
865 /*-----------------------------------------------------------------*/
866 /* pic16_sameRegs - two asmops have the same registers                   */
867 /*-----------------------------------------------------------------*/
868 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
869 {
870     int i;
871
872     if (aop1 == aop2)
873         return TRUE ;
874
875     if (aop1->type != AOP_REG ||
876         aop2->type != AOP_REG )
877         return FALSE ;
878
879     if (aop1->size != aop2->size )
880         return FALSE ;
881
882     for (i = 0 ; i < aop1->size ; i++ )
883         if (aop1->aopu.aop_reg[i] !=
884             aop2->aopu.aop_reg[i] )
885             return FALSE ;
886
887     return TRUE ;
888 }
889
890 /*-----------------------------------------------------------------*/
891 /* pic16_aopOp - allocates an asmop for an operand  :                    */
892 /*-----------------------------------------------------------------*/
893 void pic16_aopOp (operand *op, iCode *ic, bool result)
894 {
895     asmop *aop;
896     symbol *sym;
897     int i;
898
899     if (!op)
900         return ;
901
902 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
903
904     /* if this a literal */
905     if (IS_OP_LITERAL(op)) {
906         op->aop = aop = newAsmop(AOP_LIT);
907         aop->aopu.aop_lit = op->operand.valOperand;
908         aop->size = getSize(operandType(op));
909         return;
910     }
911
912     {
913       sym_link *type = operandType(op);
914 #if 0
915       if(IS_PTR_CONST(type))
916 #else
917       if(IS_CODEPTR(type))
918 #endif
919         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
920     }
921
922     /* if already has a asmop then continue */
923     if (op->aop)
924         return ;
925
926     /* if the underlying symbol has a aop */
927     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
928       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
929         op->aop = OP_SYMBOL(op)->aop;
930         return;
931     }
932
933     /* if this is a true symbol */
934     if (IS_TRUE_SYMOP(op)) {    
935         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
936       op->aop = aopForSym(ic, op, result);
937       return ;
938     }
939
940     /* this is a temporary : this has
941     only four choices :
942     a) register
943     b) spillocation
944     c) rematerialize 
945     d) conditional   
946     e) can be a return use only */
947
948     sym = OP_SYMBOL(op);
949
950         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
951     /* if the type is a conditional */
952     if (sym->regType == REG_CND) {
953         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
954         aop->size = 0;
955         return;
956     }
957
958     /* if it is spilt then two situations
959     a) is rematerialize 
960     b) has a spill location */
961     if (sym->isspilt || sym->nRegs == 0) {
962
963       DEBUGpic16_emitcode(";","%d",__LINE__);
964         /* rematerialize it NOW */
965         if (sym->remat) {
966
967             sym->aop = op->aop = aop =
968                                       aopForRemat (op);
969             aop->size = getSize(sym->type);
970             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
971             return;
972         }
973
974 #if 1
975         if (sym->accuse) {
976             int i;
977             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
978             aop->size = getSize(sym->type);
979             for ( i = 0 ; i < 1 ; i++ ) {
980                 aop->aopu.aop_str[i] = accUse[i];
981 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
982             }
983             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
984             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
985             return;  
986         }
987 #endif
988
989 #if 1
990         if (sym->ruonly ) {
991           /*
992           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
993           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
994           //pic16_allocDirReg (IC_LEFT(ic));
995           aop->size = getSize(sym->type);
996           */
997
998           unsigned i;
999
1000           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1001           aop->size = getSize(sym->type);
1002           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1003             aop->aopu.aop_str[i] = fReturn[i];
1004
1005           DEBUGpic16_emitcode(";","%d",__LINE__);
1006           return;
1007         }
1008 #endif
1009         /* else spill location  */
1010         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1011             /* force a new aop if sizes differ */
1012             sym->usl.spillLoc->aop = NULL;
1013         }
1014         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1015                             __FUNCTION__,__LINE__,
1016                             sym->usl.spillLoc->rname,
1017                             sym->rname, sym->usl.spillLoc->offset);
1018
1019         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1020         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1021         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1022                                           getSize(sym->type), 
1023                                           sym->usl.spillLoc->offset, op);
1024         aop->size = getSize(sym->type);
1025
1026         return;
1027     }
1028
1029     {
1030       sym_link *type = operandType(op);
1031 #if 0
1032       if(IS_PTR_CONST(type)) 
1033 #else
1034       if(IS_CODEPTR(type)) 
1035 #endif
1036         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1037     }
1038
1039     /* must be in a register */
1040     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1041     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1042     aop->size = sym->nRegs;
1043     for ( i = 0 ; i < sym->nRegs ;i++)
1044         aop->aopu.aop_reg[i] = sym->regs[i];
1045 }
1046
1047 /*-----------------------------------------------------------------*/
1048 /* pic16_freeAsmop - free up the asmop given to an operand               */
1049 /*----------------------------------------------------------------*/
1050 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1051 {   
1052     asmop *aop ;
1053
1054     if (!op)
1055         aop = aaop;
1056     else 
1057         aop = op->aop;
1058
1059     if (!aop)
1060         return ;
1061
1062     if (aop->freed)
1063         goto dealloc; 
1064
1065     aop->freed = 1;
1066
1067     /* depending on the asmop type only three cases need work AOP_RO
1068        , AOP_R1 && AOP_STK */
1069 #if 0
1070     switch (aop->type) {
1071         case AOP_R0 :
1072             if (_G.r0Pushed ) {
1073                 if (pop) {
1074                     pic16_emitcode ("pop","ar0");     
1075                     _G.r0Pushed--;
1076                 }
1077             }
1078             bitVectUnSetBit(ic->rUsed,R0_IDX);
1079             break;
1080
1081         case AOP_R1 :
1082             if (_G.r1Pushed ) {
1083                 if (pop) {
1084                     pic16_emitcode ("pop","ar1");
1085                     _G.r1Pushed--;
1086                 }
1087             }
1088             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1089             break;
1090
1091         case AOP_STK :
1092         {
1093             int sz = aop->size;    
1094             int stk = aop->aopu.aop_stk + aop->size;
1095             bitVectUnSetBit(ic->rUsed,R0_IDX);
1096             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1097
1098             getFreePtr(ic,&aop,FALSE);
1099             
1100             if (options.stack10bit)
1101             {
1102                 /* I'm not sure what to do here yet... */
1103                 /* #STUB */
1104                 fprintf(stderr, 
1105                         "*** Warning: probably generating bad code for "
1106                         "10 bit stack mode.\n");
1107             }
1108             
1109             if (stk) {
1110                 pic16_emitcode ("mov","a,_bp");
1111                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1112                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1113             } else {
1114                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1115             }
1116
1117             while (sz--) {
1118                 pic16_emitcode("pop","acc");
1119                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1120                 if (!sz) break;
1121                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1122             }
1123             op->aop = aop;
1124             pic16_freeAsmop(op,NULL,ic,TRUE);
1125             if (_G.r0Pushed) {
1126                 pic16_emitcode("pop","ar0");
1127                 _G.r0Pushed--;
1128             }
1129
1130             if (_G.r1Pushed) {
1131                 pic16_emitcode("pop","ar1");
1132                 _G.r1Pushed--;
1133             }       
1134         }
1135     }
1136 #endif
1137
1138 dealloc:
1139     /* all other cases just dealloc */
1140     if (op ) {
1141         op->aop = NULL;
1142         if (IS_SYMOP(op)) {
1143             OP_SYMBOL(op)->aop = NULL;    
1144             /* if the symbol has a spill */
1145             if (SPIL_LOC(op))
1146                 SPIL_LOC(op)->aop = NULL;
1147         }
1148     }
1149 }
1150
1151 /*-----------------------------------------------------------------*/
1152 /* pic16_aopGet - for fetching value of the aop                          */
1153 /*-----------------------------------------------------------------*/
1154 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1155 {
1156     char *s = buffer ;
1157     char *rs;
1158
1159     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1160
1161     /* offset is greater than size then zero */
1162     if (offset > (aop->size - 1) &&
1163         aop->type != AOP_LIT)
1164         return zero;
1165
1166     /* depending on type */
1167     switch (aop->type) {
1168         
1169     case AOP_R0:
1170     case AOP_R1:
1171         DEBUGpic16_emitcode(";","%d",__LINE__);
1172         /* if we need to increment it */       
1173         while (offset > aop->coff) {        
1174             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1175             aop->coff++;
1176         }
1177         
1178         while (offset < aop->coff) {
1179             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1180             aop->coff--;
1181         }
1182         
1183         aop->coff = offset ;
1184         if (aop->paged) {
1185             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1186             return (dname ? "acc" : "a");
1187         }       
1188         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1189         rs = Safe_calloc(1,strlen(s)+1);
1190         strcpy(rs,s);   
1191         return rs;
1192         
1193     case AOP_DPTR:
1194     case AOP_DPTR2:
1195         DEBUGpic16_emitcode(";","%d",__LINE__);
1196     if (aop->type == AOP_DPTR2)
1197     {
1198         genSetDPTR(1);
1199     }
1200     
1201         while (offset > aop->coff) {
1202             pic16_emitcode ("inc","dptr");
1203             aop->coff++;
1204         }
1205         
1206         while (offset < aop->coff) {        
1207             pic16_emitcode("lcall","__decdptr");
1208             aop->coff--;
1209         }
1210         
1211         aop->coff = offset;
1212         if (aop->code) {
1213             pic16_emitcode("clr","a");
1214             pic16_emitcode("movc","a,@a+dptr");
1215         }
1216     else {
1217             pic16_emitcode("movx","a,@dptr");
1218     }
1219             
1220     if (aop->type == AOP_DPTR2)
1221     {
1222         genSetDPTR(0);
1223     }
1224             
1225     return (dname ? "acc" : "a");
1226         
1227         
1228     case AOP_IMMD:
1229         if (bit16) 
1230             sprintf (s,"%s",aop->aopu.aop_immd);
1231         else
1232             if (offset) 
1233                 sprintf(s,"(%s >> %d)",
1234                         aop->aopu.aop_immd,
1235                         offset*8);
1236             else
1237                 sprintf(s,"%s",
1238                         aop->aopu.aop_immd);
1239         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1240         rs = Safe_calloc(1,strlen(s)+1);
1241         strcpy(rs,s);   
1242         return rs;
1243         
1244     case AOP_DIR:
1245       if (offset) {
1246         sprintf(s,"(%s + %d)",
1247                 aop->aopu.aop_dir,
1248                 offset);
1249         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1250       } else
1251             sprintf(s,"%s",aop->aopu.aop_dir);
1252         rs = Safe_calloc(1,strlen(s)+1);
1253         strcpy(rs,s);   
1254         return rs;
1255         
1256     case AOP_REG:
1257       //if (dname) 
1258       //    return aop->aopu.aop_reg[offset]->dname;
1259       //else
1260             return aop->aopu.aop_reg[offset]->name;
1261         
1262     case AOP_CRY:
1263       //pic16_emitcode(";","%d",__LINE__);
1264       return aop->aopu.aop_dir;
1265         
1266     case AOP_ACC:
1267         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1268 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1269 //        assert( 0 );
1270         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1271
1272     case AOP_LIT:
1273         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1274         rs = Safe_calloc(1,strlen(s)+1);
1275         strcpy(rs,s);   
1276         return rs;
1277         
1278     case AOP_STR:
1279         aop->coff = offset ;
1280         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1281             dname)
1282             return "acc";
1283         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1284         
1285         return aop->aopu.aop_str[offset];
1286         
1287     case AOP_PCODE:
1288       {
1289         pCodeOp *pcop = aop->aopu.pcop;
1290         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1291         if(pcop->name) {
1292           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1293           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1294           sprintf(s,"%s", pcop->name);
1295         } else
1296           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1297
1298       }
1299       rs = Safe_calloc(1,strlen(s)+1);
1300       strcpy(rs,s);   
1301       return rs;
1302
1303     }
1304
1305     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1306            "aopget got unsupported aop->type");
1307     exit(0);
1308 }
1309
1310
1311 /*-----------------------------------------------------------------*/
1312 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1313 /*-----------------------------------------------------------------*/
1314 pCodeOp *pic16_popGetTempReg(void)
1315 {
1316   pCodeOp *pcop;
1317   symbol *cfunc;
1318
1319 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1320
1321         cfunc = currFunc;
1322         currFunc = NULL;
1323
1324         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1325         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1326                 PCOR(pcop)->r->wasUsed=1;
1327                 PCOR(pcop)->r->isFree=0;
1328
1329                 /* push value on stack */
1330                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1331         }
1332
1333         currFunc = cfunc;
1334
1335   return pcop;
1336 }
1337
1338 /*-----------------------------------------------------------------*/
1339 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1340 /*-----------------------------------------------------------------*/
1341 void pic16_popReleaseTempReg(pCodeOp *pcop)
1342 {
1343         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1344
1345         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1346                 PCOR(pcop)->r->isFree = 1;
1347                 
1348                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1349         }
1350 }
1351 /*-----------------------------------------------------------------*/
1352 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1353 /*-----------------------------------------------------------------*/
1354 pCodeOp *pic16_popGetLabel(unsigned int key)
1355 {
1356
1357   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1358
1359   if(key>max_key)
1360     max_key = key;
1361
1362   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1363 }
1364
1365 /*-----------------------------------------------------------------*/
1366 /* pic16_popCopyReg - copy a pcode operator                              */
1367 /*-----------------------------------------------------------------*/
1368 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1369 {
1370   pCodeOpReg *pcor;
1371
1372   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1373   pcor->pcop.type = pc->pcop.type;
1374   if(pc->pcop.name) {
1375     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1376       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1377   } else
1378     pcor->pcop.name = NULL;
1379
1380   pcor->r = pc->r;
1381   pcor->rIdx = pc->rIdx;
1382   pcor->r->wasUsed=1;
1383
1384 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1385
1386   return PCOP(pcor);
1387 }
1388
1389 /*-----------------------------------------------------------------*/
1390 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1391 /*-----------------------------------------------------------------*/
1392 pCodeOp *pic16_popGetLit(unsigned int lit)
1393 {
1394   return pic16_newpCodeOpLit(lit);
1395 }
1396
1397 /*-----------------------------------------------------------------*/
1398 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1399 /*-----------------------------------------------------------------*/
1400 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1401 {
1402   return pic16_newpCodeOpLit2(lit, arg2);
1403 }
1404
1405
1406 /*-----------------------------------------------------------------*/
1407 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1410 {
1411   return pic16_newpCodeOpImmd(name, offset,index, 0);
1412 }
1413
1414
1415 /*-----------------------------------------------------------------*/
1416 /* pic16_popGet - asm operator to pcode operator conversion              */
1417 /*-----------------------------------------------------------------*/
1418 pCodeOp *pic16_popGetWithString(char *str)
1419 {
1420   pCodeOp *pcop;
1421
1422
1423   if(!str) {
1424     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1425     exit (1);
1426   }
1427
1428   pcop = pic16_newpCodeOp(str,PO_STR);
1429
1430   return pcop;
1431 }
1432
1433 /*-----------------------------------------------------------------*/
1434 /* pic16_popRegFromString -                                        */
1435 /*-----------------------------------------------------------------*/
1436 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1437 {
1438
1439   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1440   pcop->type = PO_DIR;
1441
1442   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1443   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1444
1445   if(!str)
1446     str = "BAD_STRING";
1447
1448   pcop->name = Safe_calloc(1,strlen(str)+1);
1449   strcpy(pcop->name,str);
1450
1451   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1452
1453   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1454   if(PCOR(pcop)->r == NULL) {
1455 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1456 //              __FUNCTION__, __LINE__, str, size, offset);
1457     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1458
1459         //fprintf(stderr, "allocating new register -> %s\n", str);
1460
1461 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1462   } else {
1463 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1464   }
1465   PCOR(pcop)->instance = offset;
1466
1467   return pcop;
1468 }
1469
1470 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1471 {
1472   pCodeOp *pcop;
1473
1474 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1475
1476         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1477         PCOR(pcop)->rIdx = rIdx;
1478         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1479         PCOR(pcop)->r->isFree = 0;
1480         PCOR(pcop)->r->wasUsed = 1;
1481
1482         pcop->type = PCOR(pcop)->r->pc_type;
1483
1484   return pcop;
1485 }
1486
1487 /*---------------------------------------------------------------------------------*/
1488 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1489 /*                 VR 030601                                                       */
1490 /*---------------------------------------------------------------------------------*/
1491 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1492 {
1493   pCodeOpReg2 *pcop2;
1494   pCodeOp *temp;
1495   
1496         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1497
1498         /* comment the following check, so errors to throw up */
1499 //      if(!pcop2)return NULL;
1500
1501         temp = pic16_popGet(aop_dst, offset);
1502         pcop2->pcop2 = temp;
1503         
1504   return PCOP(pcop2);
1505 }
1506
1507
1508
1509 /*--------------------------------------------------------------------------------.-*/
1510 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1511 /*                  VR 030601 , adapted by Hans Dorn                                */
1512 /*--------------------------------------------------------------------------------.-*/
1513 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1514 {
1515   pCodeOpReg2 *pcop2;
1516  
1517         pcop2 = (pCodeOpReg2 *)src;
1518         pcop2->pcop2 = dst;
1519         
1520         return PCOP(pcop2);
1521 }
1522
1523
1524
1525 /*---------------------------------------------------------------------------------*/
1526 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1527 /*                     movff instruction                                           */
1528 /*---------------------------------------------------------------------------------*/
1529 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1530 {
1531   pCodeOpReg2 *pcop2;
1532
1533         if(!noalloc) {
1534                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1535                 pcop2->pcop2 = pic16_popCopyReg(dst);
1536         } else {
1537                 /* the pCodeOp may be already allocated */
1538                 pcop2 = (pCodeOpReg2 *)(src);
1539                 pcop2->pcop2 = (pCodeOp *)(dst);
1540         }
1541
1542   return PCOP(pcop2);
1543 }
1544
1545
1546 /*-----------------------------------------------------------------*/
1547 /* pic16_popGet - asm operator to pcode operator conversion              */
1548 /*-----------------------------------------------------------------*/
1549 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1550 {
1551   //char *s = buffer ;
1552   char *rs;
1553   pCodeOp *pcop;
1554
1555     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1556     /* offset is greater than
1557     size then zero */
1558
1559 //    if (offset > (aop->size - 1) &&
1560 //        aop->type != AOP_LIT)
1561 //      return NULL;  //zero;
1562
1563     /* depending on type */
1564     switch (aop->type) {
1565         
1566     case AOP_R0:
1567     case AOP_R1:
1568     case AOP_DPTR:
1569     case AOP_DPTR2:
1570         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1571         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1572         assert( 0 );
1573         return NULL;
1574
1575
1576
1577     case AOP_IMMD:
1578       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1579       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1580
1581     case AOP_ACC:
1582       {
1583         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1584
1585         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1586
1587         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1588         
1589         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1590         PCOR(pcop)->rIdx = rIdx;
1591         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1592         PCOR(pcop)->r->wasUsed=1;
1593         PCOR(pcop)->r->isFree=0;
1594
1595         PCOR(pcop)->instance = offset;
1596         pcop->type = PCOR(pcop)->r->pc_type;
1597 //      rs = aop->aopu.aop_reg[offset]->name;
1598 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1599         return pcop;
1600
1601
1602 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1603 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1604
1605 //      assert( 0 );
1606       }
1607         
1608     case AOP_DIR:
1609       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1610       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1611         
1612     case AOP_REG:
1613       {
1614         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1615
1616         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1617         
1618         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1619         PCOR(pcop)->rIdx = rIdx;
1620         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1621         PCOR(pcop)->r->wasUsed=1;
1622         PCOR(pcop)->r->isFree=0;
1623
1624         PCOR(pcop)->instance = offset;
1625         pcop->type = PCOR(pcop)->r->pc_type;
1626         rs = aop->aopu.aop_reg[offset]->name;
1627         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1628         return pcop;
1629       }
1630
1631     case AOP_CRY:
1632         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1633
1634       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1635       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1636       //if(PCOR(pcop)->r == NULL)
1637       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1638       return pcop;
1639         
1640     case AOP_LIT:
1641         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1642       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1643
1644     case AOP_STR:
1645       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1646       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1647
1648       /*
1649       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1650       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1651       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1652       pcop->type = PCOR(pcop)->r->pc_type;
1653       pcop->name = PCOR(pcop)->r->name;
1654
1655       return pcop;
1656       */
1657
1658     case AOP_PCODE:
1659       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1660                           __LINE__, 
1661                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1662       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1663 #if 1
1664         switch( aop->aopu.pcop->type ) {
1665                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1666                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1667                 default:
1668                         assert( 0 );    /* should never reach here */;
1669         }
1670 #else
1671       PCOI(pcop)->offset = offset;
1672 #endif
1673       return pcop;
1674     }
1675
1676     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1677            "pic16_popGet got unsupported aop->type");
1678     exit(0);
1679 }
1680 /*-----------------------------------------------------------------*/
1681 /* pic16_aopPut - puts a string for a aop                                */
1682 /*-----------------------------------------------------------------*/
1683 void pic16_aopPut (asmop *aop, char *s, int offset)
1684 {
1685     char *d = buffer ;
1686     symbol *lbl ;
1687
1688     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1689
1690     if (aop->size && offset > ( aop->size - 1)) {
1691         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1692                "pic16_aopPut got offset > aop->size");
1693         exit(0);
1694     }
1695
1696     /* will assign value to value */
1697     /* depending on where it is ofcourse */
1698     switch (aop->type) {
1699     case AOP_DIR:
1700       if (offset) {
1701         sprintf(d,"(%s + %d)",
1702                 aop->aopu.aop_dir,offset);
1703         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1704
1705       } else
1706             sprintf(d,"%s",aop->aopu.aop_dir);
1707         
1708         if (strcmp(d,s)) {
1709           DEBUGpic16_emitcode(";","%d",__LINE__);
1710           if(strcmp(s,"W"))
1711             pic16_emitcode("movf","%s,w",s);
1712           pic16_emitcode("movwf","%s",d);
1713
1714           if(strcmp(s,"W")) {
1715             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1716             if(offset >= aop->size) {
1717               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1718               break;
1719             } else
1720               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1721           }
1722
1723           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1724
1725
1726         }
1727         break;
1728         
1729     case AOP_REG:
1730       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1731         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1732           /*
1733             if (*s == '@'           ||
1734                 strcmp(s,"r0") == 0 ||
1735                 strcmp(s,"r1") == 0 ||
1736                 strcmp(s,"r2") == 0 ||
1737                 strcmp(s,"r3") == 0 ||
1738                 strcmp(s,"r4") == 0 ||
1739                 strcmp(s,"r5") == 0 ||
1740                 strcmp(s,"r6") == 0 || 
1741                 strcmp(s,"r7") == 0 )
1742                 pic16_emitcode("mov","%s,%s  ; %d",
1743                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1744             else
1745           */
1746
1747           if(strcmp(s,"W")==0 )
1748             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1749
1750           pic16_emitcode("movwf","%s",
1751                    aop->aopu.aop_reg[offset]->name);
1752
1753           if(strcmp(s,zero)==0) {
1754             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1755
1756           } else if(strcmp(s,"W")==0) {
1757             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1758             pcop->type = PO_GPR_REGISTER;
1759
1760             PCOR(pcop)->rIdx = -1;
1761             PCOR(pcop)->r = NULL;
1762
1763             DEBUGpic16_emitcode(";","%d",__LINE__);
1764             pcop->name = Safe_strdup(s);
1765             pic16_emitpcode(POC_MOVFW,pcop);
1766             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1767           } else if(strcmp(s,one)==0) {
1768             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1769             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1770           } else {
1771             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1772           }
1773         }
1774         break;
1775         
1776     case AOP_DPTR:
1777     case AOP_DPTR2:
1778     
1779     if (aop->type == AOP_DPTR2)
1780     {
1781         genSetDPTR(1);
1782     }
1783     
1784         if (aop->code) {
1785             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1786                    "pic16_aopPut writting to code space");
1787             exit(0);
1788         }
1789         
1790         while (offset > aop->coff) {
1791             aop->coff++;
1792             pic16_emitcode ("inc","dptr");
1793         }
1794         
1795         while (offset < aop->coff) {
1796             aop->coff-- ;
1797             pic16_emitcode("lcall","__decdptr");
1798         }
1799         
1800         aop->coff = offset;
1801         
1802         /* if not in accumulater */
1803         MOVA(s);        
1804         
1805         pic16_emitcode ("movx","@dptr,a");
1806         
1807     if (aop->type == AOP_DPTR2)
1808     {
1809         genSetDPTR(0);
1810     }
1811         break;
1812         
1813     case AOP_R0:
1814     case AOP_R1:
1815         while (offset > aop->coff) {
1816             aop->coff++;
1817             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1818         }
1819         while (offset < aop->coff) {
1820             aop->coff-- ;
1821             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1822         }
1823         aop->coff = offset;
1824         
1825         if (aop->paged) {
1826             MOVA(s);           
1827             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1828             
1829         } else
1830             if (*s == '@') {
1831                 MOVA(s);
1832                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1833             } else
1834                 if (strcmp(s,"r0") == 0 ||
1835                     strcmp(s,"r1") == 0 ||
1836                     strcmp(s,"r2") == 0 ||
1837                     strcmp(s,"r3") == 0 ||
1838                     strcmp(s,"r4") == 0 ||
1839                     strcmp(s,"r5") == 0 ||
1840                     strcmp(s,"r6") == 0 || 
1841                     strcmp(s,"r7") == 0 ) {
1842                     char buffer[10];
1843                     sprintf(buffer,"a%s",s);
1844                     pic16_emitcode("mov","@%s,%s",
1845                              aop->aopu.aop_ptr->name,buffer);
1846                 } else
1847                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1848         
1849         break;
1850         
1851     case AOP_STK:
1852         if (strcmp(s,"a") == 0)
1853             pic16_emitcode("push","acc");
1854         else
1855             pic16_emitcode("push","%s",s);
1856         
1857         break;
1858         
1859     case AOP_CRY:
1860         /* if bit variable */
1861         if (!aop->aopu.aop_dir) {
1862             pic16_emitcode("clr","a");
1863             pic16_emitcode("rlc","a");
1864         } else {
1865             if (s == zero) 
1866                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1867             else
1868                 if (s == one)
1869                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1870                 else
1871                     if (!strcmp(s,"c"))
1872                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1873                     else {
1874                         lbl = newiTempLabel(NULL);
1875                         
1876                         if (strcmp(s,"a")) {
1877                             MOVA(s);
1878                         }
1879                         pic16_emitcode("clr","c");
1880                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1881                         pic16_emitcode("cpl","c");
1882                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1883                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1884                     }
1885         }
1886         break;
1887         
1888     case AOP_STR:
1889         aop->coff = offset;
1890         if (strcmp(aop->aopu.aop_str[offset],s))
1891             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1892         break;
1893         
1894     case AOP_ACC:
1895         aop->coff = offset;
1896         if (!offset && (strcmp(s,"acc") == 0))
1897             break;
1898         
1899         if (strcmp(aop->aopu.aop_str[offset],s))
1900             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1901         break;
1902
1903     default :
1904         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1905                "pic16_aopPut got unsupported aop->type");
1906         exit(0);    
1907     }    
1908
1909 }
1910
1911 /*-----------------------------------------------------------------*/
1912 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1913 /*-----------------------------------------------------------------*/
1914 static void mov2w (asmop *aop, int offset)
1915 {
1916
1917 //  if(!aop)
1918 //    return;
1919
1920         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1921
1922         if(is_LitAOp(aop))
1923                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1924         else
1925                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1926
1927 }
1928
1929
1930 /* push pcop into stack */
1931 void pic16_pushpCodeOp(pCodeOp *pcop)
1932 {
1933 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1934         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1935 }
1936
1937 /* pop pcop from stack */
1938 void pic16_poppCodeOp(pCodeOp *pcop)
1939 {
1940         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1941 }
1942
1943
1944 /*-----------------------------------------------------------------*/
1945 /* pushw - pushes wreg to stack                                    */
1946 /*-----------------------------------------------------------------*/
1947 void pushw(void)
1948 {
1949         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1950         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1951 }
1952
1953                 
1954 /*-----------------------------------------------------------------*/
1955 /* pushaop - pushes aop to stack                                   */
1956 /*-----------------------------------------------------------------*/
1957 void pushaop(asmop *aop, int offset)
1958 {
1959         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1960         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1961 }
1962
1963 /*-----------------------------------------------------------------*/
1964 /* popaop - pops aop from stack                                    */
1965 /*-----------------------------------------------------------------*/
1966 void popaop(asmop *aop, int offset)
1967 {
1968         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1969         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1970 }
1971
1972 void popaopidx(asmop *aop, int offset, int index)
1973 {
1974   int ofs=1;
1975
1976         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1977
1978         if(STACK_MODEL_LARGE)ofs++;
1979
1980         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1981         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1982 }
1983
1984 /*-----------------------------------------------------------------*/
1985 /* reAdjustPreg - points a register back to where it should        */
1986 /*-----------------------------------------------------------------*/
1987 static void reAdjustPreg (asmop *aop)
1988 {
1989     int size ;
1990
1991     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1992     aop->coff = 0;
1993     if ((size = aop->size) <= 1)
1994         return ;
1995     size-- ;
1996     switch (aop->type) {
1997         case AOP_R0 :
1998         case AOP_R1 :
1999             while (size--)
2000                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2001             break;          
2002         case AOP_DPTR :
2003         case AOP_DPTR2:
2004             if (aop->type == AOP_DPTR2)
2005             {
2006                 genSetDPTR(1);
2007             } 
2008             while (size--)
2009             {
2010                 pic16_emitcode("lcall","__decdptr");
2011             }
2012                 
2013             if (aop->type == AOP_DPTR2)
2014             {
2015                 genSetDPTR(0);
2016             }                
2017             break;  
2018
2019     }   
2020
2021 }
2022
2023
2024 #if 0
2025 /*-----------------------------------------------------------------*/
2026 /* opIsGptr: returns non-zero if the passed operand is             */   
2027 /* a generic pointer type.                                         */
2028 /*-----------------------------------------------------------------*/ 
2029 static int opIsGptr(operand *op)
2030 {
2031     sym_link *type = operandType(op);
2032     
2033     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2034     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2035     {
2036         return 1;
2037     }
2038     return 0;        
2039 }
2040 #endif
2041
2042 /*-----------------------------------------------------------------*/
2043 /* pic16_getDataSize - get the operand data size                         */
2044 /*-----------------------------------------------------------------*/
2045 int pic16_getDataSize(operand *op)
2046 {
2047     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2048
2049
2050     return AOP_SIZE(op);
2051
2052     // tsd- in the pic port, the genptr size is 1, so this code here
2053     // fails. ( in the 8051 port, the size was 4).
2054 #if 0
2055     int size;
2056     size = AOP_SIZE(op);
2057     if (size == GPTRSIZE)
2058     {
2059         sym_link *type = operandType(op);
2060         if (IS_GENPTR(type))
2061         {
2062             /* generic pointer; arithmetic operations
2063              * should ignore the high byte (pointer type).
2064              */
2065             size--;
2066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2067         }
2068     }
2069     return size;
2070 #endif
2071 }
2072
2073 /*-----------------------------------------------------------------*/
2074 /* pic16_outAcc - output Acc                                             */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_outAcc(operand *result)
2077 {
2078   int size,offset;
2079   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2080   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2081
2082
2083   size = pic16_getDataSize(result);
2084   if(size){
2085     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2086     size--;
2087     offset = 1;
2088     /* unsigned or positive */
2089     while(size--)
2090       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2091   }
2092
2093 }
2094
2095 /*-----------------------------------------------------------------*/
2096 /* pic16_outBitC - output a bit C                                  */
2097 /*                 Move to result the value of Carry flag -- VR    */
2098 /*-----------------------------------------------------------------*/
2099 void pic16_outBitC(operand *result)
2100 {
2101   int i;
2102
2103     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2104     /* if the result is bit */
2105     if (AOP_TYPE(result) == AOP_CRY) {
2106         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2107         pic16_aopPut(AOP(result),"c",0);
2108     } else {
2109
2110         i = AOP_SIZE(result);
2111         while(i--) {
2112                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2113         }
2114         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2115         
2116 /*
2117         pic16_emitcode("clr","a  ; %d", __LINE__);
2118         pic16_emitcode("rlc","a");
2119         pic16_outAcc(result);
2120 */
2121     }
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2126 /*-----------------------------------------------------------------*/
2127 void pic16_toBoolean(operand *oper)
2128 {
2129     int size = AOP_SIZE(oper) - 1;
2130     int offset = 1;
2131
2132     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2133
2134     if ( AOP_TYPE(oper) != AOP_ACC) {
2135       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2136     }
2137     while (size--) {
2138       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2139     }
2140 }
2141
2142
2143 #if !defined(GEN_Not)
2144 /*-----------------------------------------------------------------*/
2145 /* genNot - generate code for ! operation                          */
2146 /*-----------------------------------------------------------------*/
2147 static void pic16_genNot (iCode *ic)
2148 {
2149   symbol *tlbl;
2150   int size;
2151
2152   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2153   /* assign asmOps to operand & result */
2154   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2155   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2156
2157   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2158   /* if in bit space then a special case */
2159   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2160     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2161       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2162       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2163     } else {
2164       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2165       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2166       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2167     }
2168     goto release;
2169   }
2170
2171   size = AOP_SIZE(IC_LEFT(ic));
2172   if(size == 1) {
2173     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2174     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2175     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2176     goto release;
2177   }
2178   pic16_toBoolean(IC_LEFT(ic));
2179
2180   tlbl = newiTempLabel(NULL);
2181   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2182   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2183   pic16_outBitC(IC_RESULT(ic));
2184
2185  release:    
2186   /* release the aops */
2187   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2188   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2189 }
2190 #endif
2191
2192
2193 #if !defined(GEN_Cpl)
2194 /*-----------------------------------------------------------------*/
2195 /* genCpl - generate code for complement                           */
2196 /*-----------------------------------------------------------------*/
2197 static void pic16_genCpl (iCode *ic)
2198 {
2199     int offset = 0;
2200     int size ;
2201
2202
2203     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2204     /* assign asmOps to operand & result */
2205     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2206     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2207
2208     /* if both are in bit space then 
2209     a special case */
2210     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2211         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2212
2213         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2214         pic16_emitcode("cpl","c"); 
2215         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2216         goto release; 
2217     } 
2218
2219     size = AOP_SIZE(IC_RESULT(ic));
2220     while (size--) {
2221 /*
2222         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2223         MOVA(l);       
2224         pic16_emitcode("cpl","a");
2225         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2226 */
2227         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2228               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2229         } else {
2230                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2231                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2232         }
2233         offset++;
2234
2235     }
2236
2237
2238 release:
2239     /* release the aops */
2240     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2241     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2242 }
2243 #endif
2244
2245 /*-----------------------------------------------------------------*/
2246 /* genUminusFloat - unary minus for floating points                */
2247 /*-----------------------------------------------------------------*/
2248 static void genUminusFloat(operand *op,operand *result)
2249 {
2250     int size ,offset =0 ;
2251     char *l;
2252
2253     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2254     /* for this we just need to flip the 
2255     first it then copy the rest in place */
2256     size = AOP_SIZE(op) - 1;
2257     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2258
2259     MOVA(l);    
2260
2261     pic16_emitcode("cpl","acc.7");
2262     pic16_aopPut(AOP(result),"a",3);    
2263
2264     while(size--) {
2265         pic16_aopPut(AOP(result),
2266                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2267                offset);
2268         offset++;
2269     }          
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* genUminus - unary minus code generation                         */
2274 /*-----------------------------------------------------------------*/
2275 static void genUminus (iCode *ic)
2276 {
2277   int size, i;
2278   sym_link *optype, *rtype;
2279
2280         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2281         
2282         /* assign asmops */
2283         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2284         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2285
2286         /* if both in bit space then special case */
2287         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2288                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2289
2290                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2291                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2292                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2293                 
2294                 goto release; 
2295         } 
2296
2297         optype = operandType(IC_LEFT(ic));
2298         rtype = operandType(IC_RESULT(ic));
2299
2300         /* if float then do float stuff */
2301         if (IS_FLOAT(optype)) {
2302                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2303                 goto release;
2304         }
2305
2306         /* otherwise subtract from zero by taking the 2's complement */
2307         size = AOP_SIZE(IC_LEFT(ic));
2308
2309         for(i=0; i<size; i++) {
2310                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2311                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2312                 else {
2313                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2314                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2315                 }
2316         }
2317
2318         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2319         for(i=1; i<size; i++) {
2320                 emitSKPNZ;
2321                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2322         }
2323
2324 release:
2325         /* release the aops */
2326         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2327         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2328 }
2329
2330 /*-----------------------------------------------------------------*/
2331 /* saveRegisters - will look for a call and save the registers     */
2332 /*-----------------------------------------------------------------*/
2333 static void saveRegisters(iCode *lic) 
2334 {
2335     int i;
2336     iCode *ic;
2337     bitVect *rsave;
2338     sym_link *dtype;
2339
2340     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2341     /* look for call */
2342     for (ic = lic ; ic ; ic = ic->next) 
2343         if (ic->op == CALL || ic->op == PCALL)
2344             break;
2345
2346     if (!ic) {
2347         fprintf(stderr,"found parameter push with no function call\n");
2348         return ;
2349     }
2350
2351     /* if the registers have been saved already then
2352     do nothing */
2353     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2354         return ;
2355
2356     /* find the registers in use at this time 
2357     and push them away to safety */
2358     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2359                           ic->rUsed);
2360
2361     ic->regsSaved = 1;
2362     if (options.useXstack) {
2363         if (bitVectBitValue(rsave,R0_IDX))
2364             pic16_emitcode("mov","b,r0");
2365         pic16_emitcode("mov","r0,%s",spname);
2366         for (i = 0 ; i < pic16_nRegs ; i++) {
2367             if (bitVectBitValue(rsave,i)) {
2368                 if (i == R0_IDX)
2369                     pic16_emitcode("mov","a,b");
2370                 else
2371                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2372                 pic16_emitcode("movx","@r0,a");
2373                 pic16_emitcode("inc","r0");
2374             }
2375         }
2376         pic16_emitcode("mov","%s,r0",spname);
2377         if (bitVectBitValue(rsave,R0_IDX))
2378             pic16_emitcode("mov","r0,b");           
2379     }// else
2380     //for (i = 0 ; i < pic16_nRegs ; i++) {
2381     //    if (bitVectBitValue(rsave,i))
2382     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2383     //}
2384
2385     dtype = operandType(IC_LEFT(ic));
2386     if (currFunc && dtype && 
2387         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2388         IFFUNC_ISISR(currFunc->type) &&
2389         !ic->bankSaved) 
2390
2391         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2392
2393 }
2394 /*-----------------------------------------------------------------*/
2395 /* unsaveRegisters - pop the pushed registers                      */
2396 /*-----------------------------------------------------------------*/
2397 static void unsaveRegisters (iCode *ic)
2398 {
2399     int i;
2400     bitVect *rsave;
2401
2402     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2403     /* find the registers in use at this time 
2404     and push them away to safety */
2405     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2406                           ic->rUsed);
2407     
2408     if (options.useXstack) {
2409         pic16_emitcode("mov","r0,%s",spname);   
2410         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2411             if (bitVectBitValue(rsave,i)) {
2412                 pic16_emitcode("dec","r0");
2413                 pic16_emitcode("movx","a,@r0");
2414                 if (i == R0_IDX)
2415                     pic16_emitcode("mov","b,a");
2416                 else
2417                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2418             }       
2419
2420         }
2421         pic16_emitcode("mov","%s,r0",spname);
2422         if (bitVectBitValue(rsave,R0_IDX))
2423             pic16_emitcode("mov","r0,b");
2424     } //else
2425     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2426     //    if (bitVectBitValue(rsave,i))
2427     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2428     //}
2429
2430 }  
2431
2432 #if 0  // patch 14
2433 /*-----------------------------------------------------------------*/
2434 /* pushSide -                                                      */
2435 /*-----------------------------------------------------------------*/
2436 static void pushSide(operand * oper, int size)
2437 {
2438         int offset = 0;
2439     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2440         while (size--) {
2441                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2442                 if (AOP_TYPE(oper) != AOP_REG &&
2443                     AOP_TYPE(oper) != AOP_DIR &&
2444                     strcmp(l,"a") ) {
2445                         pic16_emitcode("mov","a,%s",l);
2446                         pic16_emitcode("push","acc");
2447                 } else
2448                         pic16_emitcode("push","%s",l);
2449         }
2450 }
2451 #endif // patch 14
2452
2453 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2454 {
2455 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2456
2457         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2458                 pic16_emitpcode(POC_MOVFW, src);
2459                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2460         } else {
2461                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2462                         src, pic16_popGet(AOP(op), offset)));
2463         }
2464 }
2465
2466
2467 /*-----------------------------------------------------------------*/
2468 /* assignResultValue - assign results to oper, rescall==1 is       */
2469 /*                     called from genCall() or genPCall()         */
2470 /*-----------------------------------------------------------------*/
2471 static void assignResultValue(operand * oper, int rescall)
2472 {
2473   int size = AOP_SIZE(oper);
2474
2475         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2476         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2477
2478         if(rescall) {
2479                 /* assign result from a call/pcall function() */
2480                 
2481                 /* function results are stored in a special order,
2482                  * see top of file with Function return policy, or manual */
2483
2484                 if(size <= 4) {
2485                         /* 8-bits, result in WREG */
2486                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2487                         
2488                         if(size>1) {
2489                                 /* 16-bits, result in PRODL:WREG */
2490                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2491                         }
2492                         
2493                         if(size>2) {
2494                                 /* 24-bits, result in PRODH:PRODL:WREG */
2495                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2496                         }
2497                         
2498                         if(size>3) {
2499                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2500                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2501                         }
2502                 } else {
2503                         /* >32-bits, result on stack, and FSR0 points to beginning.
2504                          * Fix stack when done */
2505                          
2506                         while (size--) {
2507 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2508 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2509                 
2510                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2511                                 GpsuedoStkPtr++;
2512                         }
2513                         
2514                         /* fix stack */
2515                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2516                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2517                         if(STACK_MODEL_LARGE) {
2518                                 emitSKPNC;
2519                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2520                         }
2521                 }                       
2522         } else {        
2523                 if(!GpsuedoStkPtr) {
2524 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2525                         /* The last byte in the assignment is in W */
2526                         size--;
2527                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2528                         GpsuedoStkPtr++;
2529                 }
2530
2531                 while (size--) {
2532 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2533 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2534                 
2535                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2536                         GpsuedoStkPtr++;
2537
2538 #if 0
2539 #if STACK_SUPPORT
2540                 if(!USE_STACK)
2541                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2542 #else
2543                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2544 #endif
2545 #endif
2546
2547                 }
2548         }
2549                 
2550 }
2551
2552
2553 /*-----------------------------------------------------------------*/
2554 /* genIpush - genrate code for pushing this gets a little complex  */
2555 /*-----------------------------------------------------------------*/
2556 static void genIpush (iCode *ic)
2557 {
2558
2559   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2560 #if 0
2561     int size, offset = 0 ;
2562     char *l;
2563
2564
2565     /* if this is not a parm push : ie. it is spill push 
2566     and spill push is always done on the local stack */
2567     if (!ic->parmPush) {
2568
2569         /* and the item is spilt then do nothing */
2570         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2571             return ;
2572
2573         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2574         size = AOP_SIZE(IC_LEFT(ic));
2575         /* push it on the stack */
2576         while(size--) {
2577             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2578             if (*l == '#') {
2579                 MOVA(l);
2580                 l = "acc";
2581             }
2582             pic16_emitcode("push","%s",l);
2583         }
2584         return ;        
2585     }
2586
2587     /* this is a paramter push: in this case we call
2588     the routine to find the call and save those
2589     registers that need to be saved */   
2590     saveRegisters(ic);
2591
2592     /* then do the push */
2593     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2594
2595
2596         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2597     size = AOP_SIZE(IC_LEFT(ic));
2598
2599     while (size--) {
2600         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2601         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2602             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2603             strcmp(l,"a") ) {
2604             pic16_emitcode("mov","a,%s",l);
2605             pic16_emitcode("push","acc");
2606         } else
2607             pic16_emitcode("push","%s",l);
2608     }       
2609
2610     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2611 #endif
2612 }
2613
2614 /*-----------------------------------------------------------------*/
2615 /* genIpop - recover the registers: can happen only for spilling   */
2616 /*-----------------------------------------------------------------*/
2617 static void genIpop (iCode *ic)
2618 {
2619   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2620 #if 0
2621     int size,offset ;
2622
2623
2624     /* if the temp was not pushed then */
2625     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2626         return ;
2627
2628     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2629     size = AOP_SIZE(IC_LEFT(ic));
2630     offset = (size-1);
2631     while (size--) 
2632         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2633                                    FALSE,TRUE));
2634
2635     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2636 #endif
2637 }
2638
2639 /*-----------------------------------------------------------------*/
2640 /* unsaverbank - restores the resgister bank from stack            */
2641 /*-----------------------------------------------------------------*/
2642 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2643 {
2644   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2645 #if 0
2646     int i;
2647     asmop *aop ;
2648     regs *r = NULL;
2649
2650     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2651     if (popPsw) {
2652         if (options.useXstack) {
2653             aop = newAsmop(0);
2654             r = getFreePtr(ic,&aop,FALSE);
2655             
2656             
2657             pic16_emitcode("mov","%s,_spx",r->name);
2658             pic16_emitcode("movx","a,@%s",r->name);
2659             pic16_emitcode("mov","psw,a");
2660             pic16_emitcode("dec","%s",r->name);
2661             
2662         }else
2663             pic16_emitcode ("pop","psw");
2664     }
2665
2666     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2667         if (options.useXstack) {       
2668             pic16_emitcode("movx","a,@%s",r->name);
2669             //pic16_emitcode("mov","(%s+%d),a",
2670             //       regspic16[i].base,8*bank+regspic16[i].offset);
2671             pic16_emitcode("dec","%s",r->name);
2672
2673         } else 
2674           pic16_emitcode("pop",""); //"(%s+%d)",
2675         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2676     }
2677
2678     if (options.useXstack) {
2679
2680         pic16_emitcode("mov","_spx,%s",r->name);
2681         pic16_freeAsmop(NULL,aop,ic,TRUE);
2682
2683     }
2684 #endif 
2685 }
2686
2687 /*-----------------------------------------------------------------*/
2688 /* saverbank - saves an entire register bank on the stack          */
2689 /*-----------------------------------------------------------------*/
2690 static void saverbank (int bank, iCode *ic, bool pushPsw)
2691 {
2692   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2693 #if 0
2694     int i;
2695     asmop *aop ;
2696     regs *r = NULL;
2697
2698     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2699     if (options.useXstack) {
2700
2701         aop = newAsmop(0);
2702         r = getFreePtr(ic,&aop,FALSE);  
2703         pic16_emitcode("mov","%s,_spx",r->name);
2704
2705     }
2706
2707     for (i = 0 ; i < pic16_nRegs ;i++) {
2708         if (options.useXstack) {
2709             pic16_emitcode("inc","%s",r->name);
2710             //pic16_emitcode("mov","a,(%s+%d)",
2711             //         regspic16[i].base,8*bank+regspic16[i].offset);
2712             pic16_emitcode("movx","@%s,a",r->name);           
2713         } else 
2714           pic16_emitcode("push","");// "(%s+%d)",
2715                      //regspic16[i].base,8*bank+regspic16[i].offset);
2716     }
2717     
2718     if (pushPsw) {
2719         if (options.useXstack) {
2720             pic16_emitcode("mov","a,psw");
2721             pic16_emitcode("movx","@%s,a",r->name);     
2722             pic16_emitcode("inc","%s",r->name);
2723             pic16_emitcode("mov","_spx,%s",r->name);       
2724             pic16_freeAsmop (NULL,aop,ic,TRUE);
2725             
2726         } else
2727             pic16_emitcode("push","psw");
2728         
2729         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2730     }
2731     ic->bankSaved = 1;
2732 #endif
2733 }
2734
2735
2736
2737 /*-----------------------------------------------------------------*/
2738 /* genCall - generates a call statement                            */
2739 /*-----------------------------------------------------------------*/
2740 static void genCall (iCode *ic)
2741 {
2742   sym_link *dtype;   
2743   int stackParms=0;
2744   
2745         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2746
2747         /* if caller saves & we have not saved then */
2748         if (!ic->regsSaved)
2749                 saveRegisters(ic);
2750
2751         /* if we are calling a function that is not using
2752          * the same register bank then we need to save the
2753          * destination registers on the stack */
2754         dtype = operandType(IC_LEFT(ic));
2755         if (currFunc && dtype && 
2756                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2757                 IFFUNC_ISISR(currFunc->type) &&
2758                 !ic->bankSaved) 
2759
2760                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2761
2762         /* if send set is not empty the assign */
2763         if (_G.sendSet) {
2764           iCode *sic;
2765
2766                 /* For the Pic port, there is no data stack.
2767                  * So parameters passed to functions are stored
2768                  * in registers. (The pCode optimizer will get
2769                  * rid of most of these :). */
2770
2771           int psuedoStkPtr=-1; 
2772           int firstTimeThruLoop = 1;
2773
2774                 _G.sendSet = reverseSet(_G.sendSet);
2775
2776                 /* First figure how many parameters are getting passed */
2777                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2778                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2779                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2780                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2781                 }
2782
2783                 stackParms = psuedoStkPtr;
2784
2785                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2786                   int size, offset = 0;
2787
2788                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2789                         size = AOP_SIZE(IC_LEFT(sic));
2790
2791                         while (size--) {
2792                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2793                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2794                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2795
2796                                 if(!firstTimeThruLoop) {
2797                                         /* If this is not the first time we've been through the loop
2798                                          * then we need to save the parameter in a temporary
2799                                          * register. The last byte of the last parameter is
2800                                          * passed in W. */
2801
2802                                         pushw();
2803                                         --psuedoStkPtr;         // sanity check
2804                                 }
2805                         
2806                                 firstTimeThruLoop=0;
2807
2808                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2809                                 offset++;
2810                         }
2811                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2812                 }
2813                 _G.sendSet = NULL;
2814         }
2815
2816         /* make the call */
2817         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2818                         OP_SYMBOL(IC_LEFT(ic))->rname :
2819                         OP_SYMBOL(IC_LEFT(ic))->name));
2820
2821         GpsuedoStkPtr=0;
2822         /* if we need assign a result value */
2823         if ((IS_ITEMP(IC_RESULT(ic)) && 
2824                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2825                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2826                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2827
2828                 _G.accInUse++;
2829                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2830                 _G.accInUse--;
2831
2832                 assignResultValue(IC_RESULT(ic), 1);
2833
2834                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2835                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2836                 
2837                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2838         }
2839
2840         if(stackParms>0) {
2841                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2842                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2843                 if(STACK_MODEL_LARGE) {
2844                         emitSKPNC;
2845                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2846                 }
2847         }
2848
2849         /* adjust the stack for parameters if required */
2850 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2851
2852         if (ic->parmBytes) {
2853           int i;
2854
2855                 if (ic->parmBytes > 3) {
2856                         pic16_emitcode("mov","a,%s",spname);
2857                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2858                         pic16_emitcode("mov","%s,a",spname);
2859                 } else 
2860                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2861                                 pic16_emitcode("dec","%s",spname);
2862         }
2863
2864 #if 0
2865         /* if register bank was saved then pop them */
2866         if (ic->bankSaved)
2867                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2868
2869         /* if we hade saved some registers then unsave them */
2870         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2871                 unsaveRegisters (ic);
2872 #endif
2873 }
2874
2875
2876
2877 /*-----------------------------------------------------------------*/   // patch 14
2878 /* genPcall - generates a call by pointer statement                */
2879 /*-----------------------------------------------------------------*/
2880
2881 // new version, created from genCall
2882
2883 static void genPcall (iCode *ic)
2884 {
2885   sym_link *dtype;   
2886   int stackParms=0;
2887   symbol *retlbl = newiTempLabel(NULL);
2888   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2889   
2890         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2891
2892         /* if caller saves & we have not saved then */
2893         if (!ic->regsSaved)
2894                 saveRegisters(ic);
2895
2896         /* if we are calling a function that is not using
2897          * the same register bank then we need to save the
2898          * destination registers on the stack */
2899         dtype = operandType(IC_LEFT(ic));
2900         if (currFunc && dtype && 
2901                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2902                 IFFUNC_ISISR(currFunc->type) &&
2903                 !ic->bankSaved) 
2904
2905                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2906
2907         /* if send set is not empty the assign */
2908         if (_G.sendSet) {
2909           iCode *sic;
2910
2911                 /* For the Pic port, there is no data stack.
2912                  * So parameters passed to functions are stored
2913                  * in registers. (The pCode optimizer will get
2914                  * rid of most of these :). */
2915
2916           int psuedoStkPtr=-1; 
2917           int firstTimeThruLoop = 1;
2918
2919                 _G.sendSet = reverseSet(_G.sendSet);
2920
2921                 /* First figure how many parameters are getting passed */
2922                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2923                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2924                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2925                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2926                 }
2927
2928                 stackParms = psuedoStkPtr;
2929
2930                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2931                   int size, offset = 0;
2932
2933                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2934                         size = AOP_SIZE(IC_LEFT(sic));
2935
2936                         while (size--) {
2937                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2938                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2939                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2940
2941                                 if(!firstTimeThruLoop) {
2942                                         /* If this is not the first time we've been through the loop
2943                                          * then we need to save the parameter in a temporary
2944                                          * register. The last byte of the last parameter is
2945                                          * passed in W. */
2946
2947                                         pushw();
2948                                         --psuedoStkPtr;         // sanity check
2949                                 }
2950                         
2951                                 firstTimeThruLoop=0;
2952
2953                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2954                                 offset++;
2955                         }
2956                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2957                 }
2958                 _G.sendSet = NULL;
2959         }
2960
2961         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2962
2963         // push return address
2964         // push $ on return stack, then replace with retlbl
2965
2966         // Note: retlbl is supplied as dummy operand to PUSH
2967         // This has the nice side effect of keeping the label from being optimized out :o)
2968         pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));      
2969
2970         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2971         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2972         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2973         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2974         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2975         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2976
2977         /* make the call by writing the pointer into pc */
2978         // FIXME Disabled writes to PCLATU because of gpsim problems
2979 #if 1
2980         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2981 #else
2982         fprintf(stderr,
2983 "WARNING: (%s:%d) PCLATU is not written because of gpsim problems\n\
2984 Correct this as soon as gpsim bug is fixed\n", __FILE__, __LINE__);
2985 #endif
2986  
2987         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2988         // note: MOVFF to PCL not allowed
2989         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2990         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2991
2992         /* return address is here: (X) */
2993         pic16_emitpLabel(retlbl->key);
2994
2995         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2996
2997         GpsuedoStkPtr=0;
2998         /* if we need assign a result value */
2999         if ((IS_ITEMP(IC_RESULT(ic)) && 
3000                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3001                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3002                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3003
3004                 _G.accInUse++;
3005                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3006                 _G.accInUse--;
3007
3008                 assignResultValue(IC_RESULT(ic), 1);
3009
3010                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3011                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3012                 
3013                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3014         }
3015
3016         if(stackParms>0) {
3017                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3018                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3019                 if(STACK_MODEL_LARGE) {
3020                         emitSKPNC;
3021                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3022                 }
3023         }
3024
3025         /* adjust the stack for parameters if required */
3026 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3027
3028         if (ic->parmBytes) {
3029           int i;
3030
3031                 if (ic->parmBytes > 3) {
3032                         pic16_emitcode("mov","a,%s",spname);
3033                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3034                         pic16_emitcode("mov","%s,a",spname);
3035                 } else 
3036                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3037                                 pic16_emitcode("dec","%s",spname);
3038         }
3039
3040         /* if register bank was saved then pop them */
3041         if (ic->bankSaved)
3042                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3043
3044         /* if we hade saved some registers then unsave them */
3045         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3046                 unsaveRegisters (ic);
3047 }
3048
3049
3050 #if 0                                                                           // patch 14
3051 // old version, kept for reference
3052
3053 /*-----------------------------------------------------------------*/
3054 /* genPcall - generates a call by pointer statement                */
3055 /*-----------------------------------------------------------------*/
3056 static void genPcall (iCode *ic)
3057 {
3058     sym_link *dtype;
3059     symbol *rlbl = newiTempLabel(NULL);
3060
3061
3062     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3063     /* if caller saves & we have not saved then */
3064     if (!ic->regsSaved)
3065         saveRegisters(ic);
3066
3067     /* if we are calling a function that is not using
3068     the same register bank then we need to save the
3069     destination registers on the stack */
3070     dtype = operandType(IC_LEFT(ic));
3071     if (currFunc && dtype && 
3072         IFFUNC_ISISR(currFunc->type) &&
3073         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3074         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3075
3076
3077     /* push the return address on to the stack */
3078     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3079     pic16_emitcode("push","acc");    
3080     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3081     pic16_emitcode("push","acc");
3082     
3083     if (options.model == MODEL_FLAT24)
3084     {
3085         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3086         pic16_emitcode("push","acc");    
3087     }
3088
3089     /* now push the calling address */
3090     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3091
3092     pushSide(IC_LEFT(ic), FPTRSIZE);
3093
3094     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3095
3096     /* if send set is not empty the assign */
3097     if (_G.sendSet) {
3098         iCode *sic ;
3099
3100         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3101              sic = setNextItem(_G.sendSet)) {
3102             int size, offset = 0;
3103             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3104             size = AOP_SIZE(IC_LEFT(sic));
3105             while (size--) {
3106                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3107                                 FALSE,FALSE);
3108                 if (strcmp(l,fReturn[offset]))
3109                     pic16_emitcode("mov","%s,%s",
3110                              fReturn[offset],
3111                              l);
3112                 offset++;
3113             }
3114             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3115         }
3116         _G.sendSet = NULL;
3117     }
3118
3119     pic16_emitcode("ret","");
3120     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3121
3122
3123     /* if we need assign a result value */
3124     if ((IS_ITEMP(IC_RESULT(ic)) &&
3125          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3126           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3127         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3128
3129         _G.accInUse++;
3130         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3131         _G.accInUse--;
3132         
3133         assignResultValue(IC_RESULT(ic), 1);
3134
3135         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3136     }
3137
3138     /* adjust the stack for parameters if 
3139     required */
3140     if (ic->parmBytes) {
3141         int i;
3142         if (ic->parmBytes > 3) {
3143             pic16_emitcode("mov","a,%s",spname);
3144             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3145             pic16_emitcode("mov","%s,a",spname);
3146         } else 
3147             for ( i = 0 ; i <  ic->parmBytes ;i++)
3148                 pic16_emitcode("dec","%s",spname);
3149
3150     }
3151
3152     /* if register bank was saved then unsave them */
3153     if (currFunc && dtype && 
3154         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3155         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3156
3157     /* if we hade saved some registers then
3158     unsave them */
3159     if (ic->regsSaved)
3160         unsaveRegisters (ic);
3161
3162 }
3163 #endif                                                                          // patch 14
3164
3165
3166 /*-----------------------------------------------------------------*/
3167 /* resultRemat - result  is rematerializable                       */
3168 /*-----------------------------------------------------------------*/
3169 static int resultRemat (iCode *ic)
3170 {
3171   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3172   if (SKIP_IC(ic) || ic->op == IFX)
3173     return 0;
3174
3175   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3176     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3177     if (sym->remat && !POINTER_SET(ic)) 
3178       return 1;
3179   }
3180
3181   return 0;
3182 }
3183
3184 #if defined(__BORLANDC__) || defined(_MSC_VER)
3185 #define STRCASECMP stricmp
3186 #else
3187 #define STRCASECMP strcasecmp
3188 #endif
3189
3190 #if 0
3191 /*-----------------------------------------------------------------*/
3192 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3193 /*-----------------------------------------------------------------*/
3194 static bool inExcludeList(char *s)
3195 {
3196   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3197     int i =0;
3198     
3199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3200     if (options.excludeRegs[i] &&
3201     STRCASECMP(options.excludeRegs[i],"none") == 0)
3202         return FALSE ;
3203
3204     for ( i = 0 ; options.excludeRegs[i]; i++) {
3205         if (options.excludeRegs[i] &&
3206         STRCASECMP(s,options.excludeRegs[i]) == 0)
3207             return TRUE;
3208     }
3209     return FALSE ;
3210 }
3211 #endif
3212
3213 /*-----------------------------------------------------------------*/
3214 /* genFunction - generated code for function entry                 */
3215 /*-----------------------------------------------------------------*/
3216 static void genFunction (iCode *ic)
3217 {
3218   symbol *sym;
3219   sym_link *ftype;
3220   
3221         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3222
3223         labelOffset += (max_key+4);
3224         max_key=0;
3225         GpsuedoStkPtr=0;
3226         _G.nRegsSaved = 0;
3227
3228         ftype = operandType(IC_LEFT(ic));
3229         sym = OP_SYMBOL(IC_LEFT(ic));
3230
3231         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3232                 /* create an absolute section at the interrupt vector:
3233                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3234           symbol *asym;
3235           char asymname[128];
3236           pBlock *apb;
3237
3238                 {
3239                   int i, found=-1;
3240
3241                         sym = OP_SYMBOL( IC_LEFT(ic));
3242                         for(i=0;i<=2;i++) {
3243                                 if(interrupts[i]->name
3244                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3245                                         found = i;
3246                                         break;
3247                                 }
3248                         }
3249                         
3250                         if(found == -1) {
3251                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3252                                         __FILE__, __LINE__, sym->name);
3253                                 assert( 0 );
3254                         }
3255                         _G.interruptvector = found;
3256                 }
3257
3258                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3259                 asym = newSymbol(asymname, 0);
3260
3261                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3262                 pic16_addpBlock( apb );
3263
3264                 pic16_addpCode2pBlock(apb,
3265                         pic16_newpCodeCharP(";-----------------------------------------"));
3266
3267
3268                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3269
3270                 pic16_addpCode2pBlock(apb,
3271                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3272                 
3273                 /* mark the end of this tiny function */
3274                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3275
3276                 {
3277                   absSym *abSym;
3278
3279                         abSym = Safe_calloc(1, sizeof(absSym));
3280                         abSym->name = Safe_strdup( asymname );
3281
3282                         switch( _G.interruptvector ) {
3283                                 case 0: abSym->address = 0x000000; break;
3284                                 case 1: abSym->address = 0x000008; break;
3285                                 case 2: abSym->address = 0x000018; break;
3286                         }
3287
3288                         addSet(&absSymSet, abSym);
3289                 }
3290         }
3291
3292
3293         /* create the function header */
3294         pic16_emitcode(";","-----------------------------------------");
3295         pic16_emitcode(";"," function %s",sym->name);
3296         pic16_emitcode(";","-----------------------------------------");
3297
3298         pic16_emitcode("","%s:",sym->rname);
3299         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3300
3301
3302         {
3303           absSym *ab;
3304
3305                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3306                         if(!strcmp(ab->name, sym->name)) {
3307                                 pic16_pBlockConvert2Absolute(pb);
3308                                 break;
3309                         }
3310
3311         }
3312
3313
3314         if(IFFUNC_ISNAKED(ftype)) {
3315                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3316                 return;
3317         }
3318         
3319         /* if critical function then turn interrupts off */
3320         if (IFFUNC_ISCRITICAL(ftype))
3321                 pic16_emitcode("clr","ea");
3322
3323         /* if this is an interrupt service routine then
3324          * save acc, b, dpl, dph  */
3325         if (IFFUNC_ISISR(sym->type)) {
3326           int i;
3327                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3328                 if(!(_G.interruptvector == 1)) {
3329
3330                         /* do not save WREG,STATUS,BSR for high priority interrupts
3331                          * because they are stored in the hardware shadow registers already */
3332                          
3333                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3334                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3335                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3336                 }
3337
3338                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3339                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3340                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3341                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3342
3343 //                pic16_pBlockConvert2ISR(pb);
3344                 
3345                 /* if any registers used */
3346                 if (sym->regsUsed) {
3347                         /* save the registers used */
3348                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3349                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3350                                 if (bitVectBitValue(sym->regsUsed,i)) {
3351 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3352 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3353 //                                                      pic16_regWithIdx(i)->name);
3354
3355                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3356                                         _G.nRegsSaved++;
3357                                 }
3358                         }
3359                 }
3360         } else {
3361                 /* emit code to setup stack frame if user enabled,
3362                  * and function is not main() */
3363          
3364 //              fprintf(stderr, "function name: %s\n", sym->name);
3365                 if(strcmp(sym->name, "main")) {
3366                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3367                         /* setup the stack frame */
3368                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3369                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3370                                 if(STACK_MODEL_LARGE)
3371                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3372                         }
3373                 }
3374
3375                 /* if callee-save to be used for this function
3376                 * then save the registers being used in this function */
3377 //              if (IFFUNC_CALLEESAVES(sym->type))
3378                 {
3379                   int i;
3380
3381 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3382
3383 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3384
3385                         /* if any registers used */
3386                         if (sym->regsUsed) {
3387                                 /* save the registers used */
3388                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3389                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3390                                         if (bitVectBitValue(sym->regsUsed,i)) {
3391
3392 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3393 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3394 //                                                              pic16_regWithIdx(i)->name);
3395
3396                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3397
3398 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3399 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3400 //                                                      &pic16_pc_postdec1, 0));
3401
3402                                                 _G.nRegsSaved++;
3403                                         }
3404                                 }
3405                         }
3406                 }
3407         }
3408
3409
3410         
3411 #if 0
3412         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3413
3414                 if (options.useXstack) {
3415                         pic16_emitcode("mov","r0,%s",spname);
3416                         pic16_emitcode("mov","a,_bp");
3417                         pic16_emitcode("movx","@r0,a");
3418                         pic16_emitcode("inc","%s",spname);
3419                 } else {
3420                         /* set up the stack */
3421                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3422                 }
3423                 pic16_emitcode ("mov","_bp,%s",spname);
3424         }
3425 #endif
3426         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3427
3428         /* adjust the stack for the function */
3429         if (sym->stack) {
3430           int i = sym->stack;
3431
3432                 if (i > 127 ) 
3433                         werror(W_STACK_OVERFLOW,sym->name);
3434
3435                 if (i > 3 && sym->recvSize < 4) {              
3436                         pic16_emitcode ("mov","a,sp");
3437                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3438                         pic16_emitcode ("mov","sp,a");
3439                 } else
3440                         while(i--)
3441                                 pic16_emitcode("inc","sp");
3442         }
3443
3444         if (sym->xstack) {
3445                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3446
3447                 pic16_emitcode ("mov","a,_spx");
3448                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3449                 pic16_emitcode ("mov","_spx,a");
3450         }
3451     
3452 }
3453
3454 /*-----------------------------------------------------------------*/
3455 /* genEndFunction - generates epilogue for functions               */
3456 /*-----------------------------------------------------------------*/
3457 static void genEndFunction (iCode *ic)
3458 {
3459     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3460
3461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3462
3463     if(IFFUNC_ISNAKED(sym->type)) {
3464         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3465         return;
3466     }
3467
3468 #if 0
3469     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3470     {
3471         pic16_emitcode ("mov","%s,_bp",spname);
3472     }
3473 #endif
3474
3475     /* if use external stack but some variables were
3476     added to the local stack then decrement the
3477     local stack */
3478     if (options.useXstack && sym->stack) {      
3479         pic16_emitcode("mov","a,sp");
3480         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3481         pic16_emitcode("mov","sp,a");
3482     }
3483
3484
3485 #if 0
3486     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3487         if (options.useXstack) {
3488             pic16_emitcode("mov","r0,%s",spname);
3489             pic16_emitcode("movx","a,@r0");
3490             pic16_emitcode("mov","_bp,a");
3491             pic16_emitcode("dec","%s",spname);
3492         }
3493         else
3494         {
3495             pic16_emitcode ("pop","_bp");
3496         }
3497     }
3498 #endif
3499
3500         if (IFFUNC_ISISR(sym->type)) {
3501                 /* now we need to restore the registers */
3502                 /* if any registers used */
3503                 if (sym->regsUsed) {
3504                   int i;
3505
3506                         /* restore registers used */
3507                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3508                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3509                                 if (bitVectBitValue(sym->regsUsed,i)) {
3510
3511 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3512 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3513 //                                                      pic16_regWithIdx(i)->name);
3514
3515                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3516
3517 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3518 //                                                      &pic16_pc_preinc1,
3519 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3520
3521                                 }
3522                         }
3523                 }
3524         
3525                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3526                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3527                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3528                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3529
3530                 if(!(_G.interruptvector == 1)) {
3531                         /* do not restore interrupt vector for WREG,STATUS,BSR
3532                          * for high priority interrupt, see genFunction */
3533                          
3534                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3535                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3536                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3537                 }
3538         
3539                 _G.interruptvector = 0;         /* sanity check */
3540
3541 //              pic16_pBlockConvert2ISR(pb);
3542
3543
3544                 /* if debug then send end of function */
3545 /*      if (options.debug && currFunc)  */
3546                 if (currFunc) {
3547                         debugFile->writeEndFunction (currFunc, ic, 1);
3548                 }
3549         
3550                 pic16_emitpcodeNULLop(POC_RETFIE);
3551         } else {
3552                 if (IFFUNC_ISCRITICAL(sym->type))
3553                         pic16_emitcode("setb","ea");
3554         
3555
3556 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3557
3558                 /* if any registers used */
3559                 if (sym->regsUsed) {
3560                   int i;
3561                         /* save the registers used */
3562                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3563                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3564                                 if (bitVectBitValue(sym->regsUsed,i)) {
3565         
3566 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3567 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3568 //                                                      pic16_regWithIdx(i)->name);
3569         
3570                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3571                                         
3572 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3573 //                                              &pic16_pc_preinc1,
3574 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3575
3576                                         _G.nRegsSaved--;
3577                                 }
3578                         }
3579                 }
3580         
3581                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3582                 /* if debug then send end of function */
3583                 if (currFunc) {
3584                         debugFile->writeEndFunction (currFunc, ic, 1);
3585                 }
3586
3587                 /* insert code to restore stack frame, if user enabled it
3588                  * and function is not main() */
3589          
3590
3591                 if(strcmp(sym->name, "main")) {
3592                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3593                                 /* restore stack frame */
3594                                 if(STACK_MODEL_LARGE)
3595                                         pic16_emitpcode(POC_MOVFF,
3596                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3597                                 pic16_emitpcode(POC_MOVFF,
3598                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3599                         }
3600                 }
3601
3602                 pic16_emitcode ("return","");
3603                 pic16_emitpcodeNULLop(POC_RETURN);
3604
3605                 /* Mark the end of a function */
3606                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3607         }
3608
3609 }
3610
3611
3612 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3613 {
3614
3615         if(is_LitOp(op)) {
3616                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3617
3618                 if(dest->type != PO_WREG)
3619                         pic16_emitpcode(POC_MOVWF, dest);
3620         } else {
3621                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3622                         pic16_popGet(AOP(op), offset), dest));
3623         }
3624 }
3625
3626 /*-----------------------------------------------------------------*/
3627 /* genRet - generate code for return statement                     */
3628 /*-----------------------------------------------------------------*/
3629 static void genRet (iCode *ic)
3630 {
3631   int size;
3632   operand *left;
3633
3634         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3635         /* if we have no return value then
3636          * just generate the "ret" */
3637         
3638         if (!IC_LEFT(ic)) 
3639                 goto jumpret;       
3640     
3641         /* we have something to return then
3642          * move the return value into place */
3643         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3644         size = AOP_SIZE(IC_LEFT(ic));
3645
3646         if(size <= 4) {
3647                 if(size>3) {
3648                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3649 //                      pic16_emitpcode(POC_MOVFF,
3650 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3651                 }
3652                 if(size>2) {
3653                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3654 //                      pic16_emitpcode(POC_MOVFF,
3655 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3656                 }
3657                 if(size>1) {
3658                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3659 //                      pic16_emitpcode(POC_MOVFF,
3660 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3661                 }
3662
3663 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3664
3665                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3666 //              pic16_emitpcode(POC_MOVFF,
3667 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3668
3669         } else {
3670                 /* >32-bits, setup stack and FSR0 */
3671                 while (size--) {
3672 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3673 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3674
3675                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3676
3677 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3678                         GpsuedoStkPtr++;
3679                 }
3680                         
3681                 /* setup FSR0 */
3682                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3683                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3684
3685                 if(STACK_MODEL_LARGE) {
3686                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3687                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3688                 } else {
3689                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3690                 }
3691         }
3692                                 
3693 #if 0
3694         /* old code, left here for reference -- VR */    
3695         while (size--) {
3696           char *l ;
3697
3698                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3699                         /* #NOCHANGE */
3700                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3701                         pic16_emitpcomment("push %s",l);
3702                         pushed++;
3703                 } else {
3704                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3705                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3706                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3707                         
3708                         if (strcmp(fReturn[offset],l)) {
3709                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3710                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3711                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3712                                 } else {
3713                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3714                                 }
3715                                 
3716                                 if(size) {
3717                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3718                                 }
3719                                 offset++;
3720                         }
3721                 }
3722         }    
3723
3724         if (pushed) {
3725                 while(pushed) {
3726                         pushed--;
3727                         if (strcmp(fReturn[pushed],"a"))
3728                                 pic16_emitcode("pop",fReturn[pushed]);
3729                         else
3730                                 pic16_emitcode("pop","acc");
3731                 }
3732         }
3733 #endif
3734
3735
3736         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3737     
3738 jumpret:
3739         /* generate a jump to the return label
3740          * if the next is not the return statement */
3741         if (!(ic->next && ic->next->op == LABEL
3742                 && IC_LABEL(ic->next) == returnLabel)) {
3743         
3744                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3745                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3746         }
3747 }
3748
3749 /*-----------------------------------------------------------------*/
3750 /* genLabel - generates a label                                    */
3751 /*-----------------------------------------------------------------*/
3752 static void genLabel (iCode *ic)
3753 {
3754
3755
3756     /* special case never generate */
3757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3758     if (IC_LABEL(ic) == entryLabel)
3759         return ;
3760
3761     pic16_emitpLabel(IC_LABEL(ic)->key);
3762     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3763 }
3764
3765 /*-----------------------------------------------------------------*/
3766 /* genGoto - generates a goto                                      */
3767 /*-----------------------------------------------------------------*/
3768 //tsd
3769 static void genGoto (iCode *ic)
3770 {
3771   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3772   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3773 }
3774
3775
3776 /*-----------------------------------------------------------------*/
3777 /* genMultbits :- multiplication of bits                           */
3778 /*-----------------------------------------------------------------*/
3779 static void genMultbits (operand *left, 
3780                          operand *right, 
3781                          operand *result)
3782 {
3783   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3784
3785   if(!pic16_sameRegs(AOP(result),AOP(right)))
3786     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3787
3788   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3789   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3790   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3791
3792 }
3793
3794
3795 /*-----------------------------------------------------------------*/
3796 /* genMultOneByte : 8 bit multiplication & division                */
3797 /*-----------------------------------------------------------------*/
3798 static void genMultOneByte (operand *left,
3799                             operand *right,
3800                             operand *result)
3801 {
3802
3803   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3804   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3805   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3806
3807   /* (if two literals, the value is computed before) */
3808   /* if one literal, literal on the right */
3809   if (AOP_TYPE(left) == AOP_LIT){
3810     operand *t = right;
3811     right = left;
3812     left = t;
3813   }
3814
3815         /* size is already checked in genMult == 1 */
3816 //      size = AOP_SIZE(result);
3817
3818         if (AOP_TYPE(right) == AOP_LIT){
3819                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3820                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3821                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3822                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3823         } else {
3824                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3825                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3826                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3827                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3828         }
3829         
3830         pic16_genMult8X8_8 (left, right,result);
3831 }
3832
3833 /*-----------------------------------------------------------------*/
3834 /* genMultOneWord : 16 bit multiplication                          */
3835 /*-----------------------------------------------------------------*/
3836 static void genMultOneWord (operand *left,
3837                             operand *right,
3838                             operand *result)
3839 {
3840
3841         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3842         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3843         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3844
3845         /* (if two literals, the value is computed before)
3846          * if one literal, literal on the right */
3847         if (AOP_TYPE(left) == AOP_LIT){
3848           operand *t = right;
3849                 right = left;
3850                 left = t;
3851         }
3852
3853         /* size is checked already == 2 */
3854 //      size = AOP_SIZE(result);
3855
3856         if (AOP_TYPE(right) == AOP_LIT) {
3857                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3858                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3859                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3860                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3861         } else {
3862                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3863                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3864                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3865                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3866         }
3867         
3868         pic16_genMult16X16_16(left, right,result);
3869 }
3870
3871 /*-----------------------------------------------------------------*/
3872 /* genMultOneLong : 32 bit multiplication                          */
3873 /*-----------------------------------------------------------------*/
3874 static void genMultOneLong (operand *left,
3875                             operand *right,
3876                             operand *result)
3877 {
3878
3879         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3880         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3881         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3882
3883         /* (if two literals, the value is computed before)
3884          * if one literal, literal on the right */
3885         if (AOP_TYPE(left) == AOP_LIT){
3886           operand *t = right;
3887                 right = left;
3888                 left = t;
3889         }
3890
3891         /* size is checked already == 4 */
3892 //      size = AOP_SIZE(result);
3893
3894         if (AOP_TYPE(right) == AOP_LIT) {
3895                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3896                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3897                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3898                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3899         } else {
3900                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3901                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3902                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3903                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3904         }
3905         
3906         pic16_genMult32X32_32(left, right,result);
3907 }
3908
3909
3910
3911 /*-----------------------------------------------------------------*/
3912 /* genMult - generates code for multiplication                     */
3913 /*-----------------------------------------------------------------*/
3914 static void genMult (iCode *ic)
3915 {
3916   operand *left = IC_LEFT(ic);
3917   operand *right = IC_RIGHT(ic);
3918   operand *result= IC_RESULT(ic);   
3919
3920         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3921         /* assign the amsops */
3922         pic16_aopOp (left,ic,FALSE);
3923         pic16_aopOp (right,ic,FALSE);
3924         pic16_aopOp (result,ic,TRUE);
3925
3926         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3927
3928         /* special cases first *
3929         * both are bits */
3930         if (AOP_TYPE(left) == AOP_CRY
3931                 && AOP_TYPE(right)== AOP_CRY) {
3932                 genMultbits(left,right,result);
3933           goto release ;
3934         }
3935
3936         /* if both are of size == 1 */
3937         if(AOP_SIZE(left) == 1
3938                 && AOP_SIZE(right) == 1) {
3939                 genMultOneByte(left,right,result);
3940           goto release ;
3941         }
3942
3943         /* if both are of size == 2 */
3944         if(AOP_SIZE(left) == 2
3945                 && AOP_SIZE(right) == 2) {
3946                 genMultOneWord(left, right, result);
3947           goto release;
3948         }
3949         
3950         /* if both are of size == 4 */
3951         if(AOP_SIZE(left) == 4
3952                 && AOP_SIZE(right) == 4) {
3953                 genMultOneLong(left, right, result);
3954           goto release;
3955         }
3956         
3957         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3958
3959
3960         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3961         /* should have been converted to function call */
3962         assert(0) ;
3963
3964 release :
3965         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3966         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3967         pic16_freeAsmop(result,NULL,ic,TRUE); 
3968 }
3969
3970 /*-----------------------------------------------------------------*/
3971 /* genDivbits :- division of bits                                  */
3972 /*-----------------------------------------------------------------*/
3973 static void genDivbits (operand *left, 
3974                         operand *right, 
3975                         operand *result)
3976 {
3977
3978     char *l;
3979
3980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3981     /* the result must be bit */    
3982     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3983     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3984
3985     MOVA(l);    
3986
3987     pic16_emitcode("div","ab");
3988     pic16_emitcode("rrc","a");
3989     pic16_aopPut(AOP(result),"c",0);
3990 }
3991
3992 /*-----------------------------------------------------------------*/
3993 /* genDivOneByte : 8 bit division                                  */
3994 /*-----------------------------------------------------------------*/
3995 static void genDivOneByte (operand *left,
3996                            operand *right,
3997                            operand *result)
3998 {
3999     sym_link *opetype = operandType(result);
4000     char *l ;
4001     symbol *lbl ;
4002     int size,offset;
4003
4004         /* result = divident / divisor
4005          * - divident may be a register or a literal,
4006          * - divisor may be a register or a literal,
4007          * so there are 3 cases (literal / literal is optimized
4008          * by the front-end) to handle.
4009          * In addition we must handle signed and unsigned, which
4010          * result in 6 final different cases -- VR */
4011
4012     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4013     size = AOP_SIZE(result) - 1;
4014     offset = 1;
4015     /* signed or unsigned */
4016     if (SPEC_USIGN(opetype)) {
4017       pCodeOp *pct1,    /* count */
4018                 *pct2,  /* reste */
4019                 *pct3;  /* temp */
4020       symbol *label1, *label2, *label3;;
4021
4022
4023         /* unsigned is easy */
4024
4025         pct1 = pic16_popGetTempReg();
4026         pct2 = pic16_popGetTempReg();
4027         pct3 = pic16_popGetTempReg();
4028         
4029         label1 = newiTempLabel(NULL);
4030         label2 = newiTempLabel(NULL);
4031         label3 = newiTempLabel(NULL);
4032
4033         /* the following algorithm is extracted from divuint.c */
4034
4035         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4036         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4037         
4038         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4039
4040         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4041         
4042         pic16_emitpLabel(label1->key);
4043         
4044         emitCLRC;
4045         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4046
4047
4048         emitCLRC;
4049         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4050         
4051
4052         emitSKPNC;
4053         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4054         
4055         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4056         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4057         
4058         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4059         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4060         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4061         
4062         pic16_emitpLabel( label3->key );
4063         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4064         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4065         
4066         
4067
4068         pic16_emitpLabel(label2->key);
4069         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4070         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4071         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4072         
4073         /* result is in wreg */
4074         if(AOP_TYPE(result) != AOP_ACC)
4075                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4076
4077         pic16_popReleaseTempReg( pct3 );
4078         pic16_popReleaseTempReg( pct2 );
4079         pic16_popReleaseTempReg( pct1 );
4080
4081         return ;
4082     }
4083
4084     /* signed is a little bit more difficult */
4085
4086     /* save the signs of the operands */
4087     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4088     MOVA(l);    
4089     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4090     pic16_emitcode("push","acc"); /* save it on the stack */
4091
4092     /* now sign adjust for both left & right */
4093     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4094     MOVA(l);       
4095     lbl = newiTempLabel(NULL);
4096     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4097     pic16_emitcode("cpl","a");   
4098     pic16_emitcode("inc","a");
4099     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4100     pic16_emitcode("mov","b,a");
4101
4102     /* sign adjust left side */
4103     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4104     MOVA(l);
4105
4106     lbl = newiTempLabel(NULL);
4107     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4108     pic16_emitcode("cpl","a");
4109     pic16_emitcode("inc","a");
4110     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4111
4112     /* now the division */
4113     pic16_emitcode("div","ab");
4114     /* we are interested in the lower order
4115     only */
4116     pic16_emitcode("mov","b,a");
4117     lbl = newiTempLabel(NULL);
4118     pic16_emitcode("pop","acc");   
4119     /* if there was an over flow we don't 
4120     adjust the sign of the result */
4121     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4122     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4123     CLRC;
4124     pic16_emitcode("clr","a");
4125     pic16_emitcode("subb","a,b");
4126     pic16_emitcode("mov","b,a");
4127     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4128
4129     /* now we are done */
4130     pic16_aopPut(AOP(result),"b",0);
4131     if(size > 0){
4132         pic16_emitcode("mov","c,b.7");
4133         pic16_emitcode("subb","a,acc");   
4134     }
4135     while (size--)
4136         pic16_aopPut(AOP(result),"a",offset++);
4137
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genDiv - generates code for division                            */
4142 /*-----------------------------------------------------------------*/
4143 static void genDiv (iCode *ic)
4144 {
4145     operand *left = IC_LEFT(ic);
4146     operand *right = IC_RIGHT(ic);
4147     operand *result= IC_RESULT(ic);   
4148
4149
4150         /* Division is a very lengthy algorithm, so it is better
4151          * to call support routines than inlining algorithm.
4152          * Division functions written here just in case someone
4153          * wants to inline and not use the support libraries -- VR */
4154
4155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4156     /* assign the amsops */
4157     pic16_aopOp (left,ic,FALSE);
4158     pic16_aopOp (right,ic,FALSE);
4159     pic16_aopOp (result,ic,TRUE);
4160
4161     /* special cases first */
4162     /* both are bits */
4163     if (AOP_TYPE(left) == AOP_CRY &&
4164         AOP_TYPE(right)== AOP_CRY) {
4165         genDivbits(left,right,result);
4166         goto release ;
4167     }
4168
4169     /* if both are of size == 1 */
4170     if (AOP_SIZE(left) == 1 &&
4171         AOP_SIZE(right) == 1 ) {
4172         genDivOneByte(left,right,result);
4173         goto release ;
4174     }
4175
4176     /* should have been converted to function call */
4177     assert(0);
4178 release :
4179     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4180     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4181     pic16_freeAsmop(result,NULL,ic,TRUE); 
4182 }
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genModbits :- modulus of bits                                   */
4186 /*-----------------------------------------------------------------*/
4187 static void genModbits (operand *left, 
4188                         operand *right, 
4189                         operand *result)
4190 {
4191
4192     char *l;
4193
4194     /* the result must be bit */    
4195     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4196     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4197
4198     MOVA(l);       
4199
4200     pic16_emitcode("div","ab");
4201     pic16_emitcode("mov","a,b");
4202     pic16_emitcode("rrc","a");
4203     pic16_aopPut(AOP(result),"c",0);
4204 }
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genModOneByte : 8 bit modulus                                   */
4208 /*-----------------------------------------------------------------*/
4209 static void genModOneByte (operand *left,
4210                            operand *right,
4211                            operand *result)
4212 {
4213     sym_link *opetype = operandType(result);
4214     char *l ;
4215     symbol *lbl ;
4216
4217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4218     /* signed or unsigned */
4219     if (SPEC_USIGN(opetype)) {
4220         /* unsigned is easy */
4221         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4222         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4223         MOVA(l);    
4224         pic16_emitcode("div","ab");
4225         pic16_aopPut(AOP(result),"b",0);
4226         return ;
4227     }
4228
4229     /* signed is a little bit more difficult */
4230
4231     /* save the signs of the operands */
4232     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4233     MOVA(l);
4234
4235     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4236     pic16_emitcode("push","acc"); /* save it on the stack */
4237
4238     /* now sign adjust for both left & right */
4239     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4240     MOVA(l);
4241
4242     lbl = newiTempLabel(NULL);
4243     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4244     pic16_emitcode("cpl","a");   
4245     pic16_emitcode("inc","a");
4246     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4247     pic16_emitcode("mov","b,a"); 
4248
4249     /* sign adjust left side */
4250     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4251     MOVA(l);
4252
4253     lbl = newiTempLabel(NULL);
4254     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4255     pic16_emitcode("cpl","a");   
4256     pic16_emitcode("inc","a");
4257     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4258
4259     /* now the multiplication */
4260     pic16_emitcode("div","ab");
4261     /* we are interested in the lower order
4262     only */
4263     lbl = newiTempLabel(NULL);
4264     pic16_emitcode("pop","acc");   
4265     /* if there was an over flow we don't 
4266     adjust the sign of the result */
4267     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4268     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4269     CLRC ;
4270     pic16_emitcode("clr","a");
4271     pic16_emitcode("subb","a,b");
4272     pic16_emitcode("mov","b,a");
4273     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4274
4275     /* now we are done */
4276     pic16_aopPut(AOP(result),"b",0);
4277
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* genMod - generates code for division                            */
4282 /*-----------------------------------------------------------------*/
4283 static void genMod (iCode *ic)
4284 {
4285     operand *left = IC_LEFT(ic);
4286     operand *right = IC_RIGHT(ic);
4287     operand *result= IC_RESULT(ic);  
4288
4289     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4290     /* assign the amsops */
4291     pic16_aopOp (left,ic,FALSE);
4292     pic16_aopOp (right,ic,FALSE);
4293     pic16_aopOp (result,ic,TRUE);
4294
4295     /* special cases first */
4296     /* both are bits */
4297     if (AOP_TYPE(left) == AOP_CRY &&
4298         AOP_TYPE(right)== AOP_CRY) {
4299         genModbits(left,right,result);
4300         goto release ;
4301     }
4302
4303     /* if both are of size == 1 */
4304     if (AOP_SIZE(left) == 1 &&
4305         AOP_SIZE(right) == 1 ) {
4306         genModOneByte(left,right,result);
4307         goto release ;
4308     }
4309
4310     /* should have been converted to function call */
4311     assert(0);
4312
4313 release :
4314     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4315     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4316     pic16_freeAsmop(result,NULL,ic,TRUE); 
4317 }
4318
4319 /*-----------------------------------------------------------------*/
4320 /* genIfxJump :- will create a jump depending on the ifx           */
4321 /*-----------------------------------------------------------------*/
4322 /*
4323   note: May need to add parameter to indicate when a variable is in bit space.
4324 */
4325 static void genIfxJump (iCode *ic, char *jval)
4326 {
4327
4328     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4329     /* if true label then we jump if condition
4330     supplied is true */
4331     if ( IC_TRUE(ic) ) {
4332
4333         if(strcmp(jval,"a") == 0)
4334           emitSKPZ;
4335         else if (strcmp(jval,"c") == 0)
4336           emitSKPC;
4337         else {
4338           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4339           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4340         }
4341
4342         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4343         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4344
4345     }
4346     else {
4347         /* false label is present */
4348         if(strcmp(jval,"a") == 0)
4349           emitSKPNZ;
4350         else if (strcmp(jval,"c") == 0)
4351           emitSKPNC;
4352         else {
4353           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4354           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4355         }
4356
4357         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4358         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4359
4360     }
4361
4362
4363     /* mark the icode as generated */
4364     ic->generated = 1;
4365 }
4366
4367 #if 0
4368 // not needed ATM
4369
4370 /*-----------------------------------------------------------------*/
4371 /* genSkip                                                         */
4372 /*-----------------------------------------------------------------*/
4373 static void genSkip(iCode *ifx,int status_bit)
4374 {
4375   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4376   if(!ifx)
4377     return;
4378
4379   if ( IC_TRUE(ifx) ) {
4380     switch(status_bit) {
4381     case 'z':
4382       emitSKPNZ;
4383       break;
4384
4385     case 'c':
4386       emitSKPNC;
4387       break;
4388
4389     case 'd':
4390       emitSKPDC;
4391       break;
4392
4393     }
4394
4395     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4396     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4397
4398   } else {
4399
4400     switch(status_bit) {
4401
4402     case 'z':
4403       emitSKPZ;
4404       break;
4405
4406     case 'c':
4407       emitSKPC;
4408       break;
4409
4410     case 'd':
4411       emitSKPDC;
4412       break;
4413     }
4414     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4415     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4416
4417   }
4418
4419 }
4420 #endif
4421
4422 /*-----------------------------------------------------------------*/
4423 /* genSkipc                                                        */
4424 /*-----------------------------------------------------------------*/
4425 static void genSkipc(resolvedIfx *rifx)
4426 {
4427   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4428   
4429   if(!rifx)
4430     return;
4431
4432   if(rifx->condition)
4433     emitSKPC;
4434   else
4435     emitSKPNC;
4436
4437   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4438   rifx->generated = 1;
4439 }
4440
4441 /*-----------------------------------------------------------------*/
4442 /* genSkipz2                                                       */
4443 /*-----------------------------------------------------------------*/
4444 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4445 {
4446   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4447   
4448   if(!rifx)
4449     return;
4450
4451   if( (rifx->condition ^ invert_condition) & 1)
4452     emitSKPZ;
4453   else
4454     emitSKPNZ;
4455
4456   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4457   rifx->generated = 1;
4458 }
4459
4460 #if 0
4461 /*-----------------------------------------------------------------*/
4462 /* genSkipz                                                        */
4463 /*-----------------------------------------------------------------*/
4464 static void genSkipz(iCode *ifx, int condition)
4465 {
4466   if(!ifx)
4467     return;
4468
4469   if(condition)
4470     emitSKPNZ;
4471   else
4472     emitSKPZ;
4473
4474   if ( IC_TRUE(ifx) )
4475     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4476   else
4477     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4478
4479   if ( IC_TRUE(ifx) )
4480     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4481   else
4482     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4483
4484 }
4485 #endif
4486
4487 /*-----------------------------------------------------------------*/
4488 /* genSkipCond                                                     */
4489 /*-----------------------------------------------------------------*/
4490 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4491 {
4492   if(!rifx)
4493     return;
4494
4495   if(rifx->condition)
4496     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4497   else
4498     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4499
4500
4501   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4502   rifx->generated = 1;
4503 }
4504
4505 #if 0
4506 /*-----------------------------------------------------------------*/
4507 /* genChkZeroes :- greater or less than comparison                 */
4508 /*     For each byte in a literal that is zero, inclusive or the   */
4509 /*     the corresponding byte in the operand with W                */
4510 /*     returns true if any of the bytes are zero                   */
4511 /*-----------------------------------------------------------------*/
4512 static int genChkZeroes(operand *op, int lit,  int size)
4513 {
4514
4515   int i;
4516   int flag =1;
4517
4518   while(size--) {
4519     i = (lit >> (size*8)) & 0xff;
4520
4521     if(i==0) {
4522       if(flag) 
4523         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4524       else
4525         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4526       flag = 0;
4527     }
4528   }
4529
4530   return (flag==0);
4531 }
4532 #endif
4533
4534 /*-----------------------------------------------------------------*/
4535 /* genCmp :- greater or less than comparison                       */
4536 /*-----------------------------------------------------------------*/
4537 static void genCmp (operand *left,operand *right,
4538                     operand *result, iCode *ifx, int sign)
4539 {
4540   int size; //, offset = 0 ;
4541   unsigned long lit = 0L,i = 0;
4542   resolvedIfx rFalseIfx;
4543   //  resolvedIfx rTrueIfx;
4544   symbol *truelbl;
4545   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4546 /*
4547   if(ifx) {
4548     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4549     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4550   }
4551 */
4552
4553   resolveIfx(&rFalseIfx,ifx);
4554   truelbl  = newiTempLabel(NULL);
4555   size = max(AOP_SIZE(left),AOP_SIZE(right));
4556
4557   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4558
4559 #define _swapp
4560
4561   /* if literal is on the right then swap with left */
4562   if ((AOP_TYPE(right) == AOP_LIT)) {
4563     operand *tmp = right ;
4564     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4565     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4566 #ifdef _swapp
4567
4568     lit = (lit - 1) & mask;
4569     right = left;
4570     left = tmp;
4571     rFalseIfx.condition ^= 1;
4572 #endif
4573
4574   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4575     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4576   }
4577
4578
4579   //if(IC_TRUE(ifx) == NULL)
4580   /* if left & right are bit variables */
4581   if (AOP_TYPE(left) == AOP_CRY &&
4582       AOP_TYPE(right) == AOP_CRY ) {
4583     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4584     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4585   } else {
4586     /* subtract right from left if at the
4587        end the carry flag is set then we know that
4588        left is greater than right */
4589
4590     symbol *lbl  = newiTempLabel(NULL);
4591
4592 #if 0
4593         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4594                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4595 #endif
4596
4597 #ifndef _swapp
4598     if(AOP_TYPE(right) == AOP_LIT) {
4599
4600       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4601
4602       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4603
4604       /* special cases */
4605
4606       if(lit == 0) {
4607
4608         if(sign != 0) 
4609           genSkipCond(&rFalseIfx,left,size-1,7);
4610         else 
4611           /* no need to compare to 0...*/
4612           /* NOTE: this is a de-generate compare that most certainly 
4613            *       creates some dead code. */
4614           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4615
4616         if(ifx) ifx->generated = 1;
4617         return;
4618
4619       }
4620       size--;
4621
4622       if(size == 0) {
4623         //i = (lit >> (size*8)) & 0xff;
4624         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4625         
4626         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4627
4628         i = ((0-lit) & 0xff);
4629         if(sign) {
4630           if( i == 0x81) { 
4631             /* lit is 0x7f, all signed chars are less than
4632              * this except for 0x7f itself */
4633             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4634             genSkipz2(&rFalseIfx,0);
4635           } else {
4636             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4637             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4638             genSkipc(&rFalseIfx);
4639           }
4640
4641         } else {
4642           if(lit == 1) {
4643             genSkipz2(&rFalseIfx,1);
4644           } else {
4645             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4646             genSkipc(&rFalseIfx);
4647           }
4648         }
4649
4650         if(ifx) ifx->generated = 1;
4651         return;
4652       }
4653
4654       /* chars are out of the way. now do ints and longs */
4655
4656
4657       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4658         
4659       /* special cases */
4660
4661       if(sign) {
4662
4663         if(lit == 0) {
4664           genSkipCond(&rFalseIfx,left,size,7);
4665           if(ifx) ifx->generated = 1;
4666           return;
4667         }
4668
4669         if(lit <0x100) {
4670           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4671
4672           //rFalseIfx.condition ^= 1;
4673           //genSkipCond(&rFalseIfx,left,size,7);
4674           //rFalseIfx.condition ^= 1;
4675
4676           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4677           if(rFalseIfx.condition)
4678             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4679           else
4680             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4681
4682           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4683           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4684           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4685
4686           while(size > 1)
4687             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4688
4689           if(rFalseIfx.condition) {
4690             emitSKPZ;
4691             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4692
4693           } else {
4694             emitSKPNZ;
4695           }
4696
4697           genSkipc(&rFalseIfx);
4698           pic16_emitpLabel(truelbl->key);
4699           if(ifx) ifx->generated = 1;
4700           return;
4701
4702         }
4703
4704         if(size == 1) {
4705
4706           if( (lit & 0xff) == 0) {
4707             /* lower byte is zero */
4708             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4709             i = ((lit >> 8) & 0xff) ^0x80;
4710             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4711             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4712             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4713             genSkipc(&rFalseIfx);
4714
4715
4716             if(ifx) ifx->generated = 1;
4717             return;
4718
4719           }
4720         } else {
4721           /* Special cases for signed longs */
4722           if( (lit & 0xffffff) == 0) {
4723             /* lower byte is zero */
4724             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4725             i = ((lit >> 8*3) & 0xff) ^0x80;
4726             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4727             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4728             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4729             genSkipc(&rFalseIfx);
4730
4731
4732             if(ifx) ifx->generated = 1;
4733             return;
4734
4735           }
4736
4737         }
4738
4739
4740         if(lit & (0x80 << (size*8))) {
4741           /* lit is negative */
4742           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4743
4744           //genSkipCond(&rFalseIfx,left,size,7);
4745
4746           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4747
4748           if(rFalseIfx.condition)
4749             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4750           else
4751             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4752
4753
4754         } else {
4755           /* lit is positive */
4756           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4757           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4758           if(rFalseIfx.condition)
4759             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4760           else
4761             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4762
4763         }
4764
4765         /*
4766           This works, but is only good for ints.
4767           It also requires a "known zero" register.
4768           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4769           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4770           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4771           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4772           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4773           genSkipc(&rFalseIfx);
4774
4775           pic16_emitpLabel(truelbl->key);
4776           if(ifx) ifx->generated = 1;
4777           return;
4778         **/
4779           
4780         /* There are no more special cases, so perform a general compare */
4781   
4782         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4783         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4784
4785         while(size--) {
4786
4787           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4788           emitSKPNZ;
4789           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4790         }
4791         //rFalseIfx.condition ^= 1;
4792         genSkipc(&rFalseIfx);
4793
4794         pic16_emitpLabel(truelbl->key);
4795
4796         if(ifx) ifx->generated = 1;
4797         return;
4798
4799
4800       }
4801
4802
4803       /* sign is out of the way. So now do an unsigned compare */
4804       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4805
4806
4807       /* General case - compare to an unsigned literal on the right.*/
4808
4809       i = (lit >> (size*8)) & 0xff;
4810       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4811       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4812       while(size--) {
4813         i = (lit >> (size*8)) & 0xff;
4814
4815         if(i) {
4816           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4817           emitSKPNZ;
4818           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4819         } else {
4820           /* this byte of the lit is zero, 
4821            *if it's not the last then OR in the variable */
4822           if(size)
4823             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4824         }
4825       }
4826
4827
4828       pic16_emitpLabel(lbl->key);
4829 //      pic16_emitpLabel(truelbl->key);
4830       //if(emitFinalCheck)
4831       genSkipc(&rFalseIfx);
4832       if(sign)
4833         pic16_emitpLabel(truelbl->key);
4834
4835       if(ifx) ifx->generated = 1;
4836       return;
4837
4838
4839     }
4840 #endif  // _swapp
4841
4842     if(AOP_TYPE(left) == AOP_LIT) {
4843       //symbol *lbl = newiTempLabel(NULL);
4844
4845       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4846
4847
4848       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4849
4850       /* Special cases */
4851       if((lit == 0) && (sign == 0)){
4852
4853         size--;
4854         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4855         while(size) 
4856           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4857
4858         genSkipz2(&rFalseIfx,0);
4859         if(ifx) ifx->generated = 1;
4860         return;
4861       }
4862
4863       if(size==1) {
4864         /* Special cases */
4865         lit &= 0xff;
4866         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4867           /* degenerate compare can never be true */
4868           if(rFalseIfx.condition == 0)
4869             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4870
4871           if(ifx) ifx->generated = 1;
4872           return;
4873         }
4874
4875         if(sign) {
4876           /* signed comparisons to a literal byte */
4877
4878           int lp1 = (lit+1) & 0xff;
4879
4880           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4881           switch (lp1) {
4882           case 0:
4883             rFalseIfx.condition ^= 1;
4884             genSkipCond(&rFalseIfx,right,0,7);
4885             break;
4886           case 0x7f:
4887             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4888             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4889             genSkipz2(&rFalseIfx,1);
4890             break;
4891           default:
4892             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4893             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4894             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4895             rFalseIfx.condition ^= 1;
4896             genSkipc(&rFalseIfx);
4897             break;
4898           }
4899         } else {
4900           /* unsigned comparisons to a literal byte */
4901
4902           switch(lit & 0xff ) {
4903           case 0:
4904             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4905             genSkipz2(&rFalseIfx,0);
4906             break;
4907           case 0x7f:
4908             rFalseIfx.condition ^= 1;
4909             genSkipCond(&rFalseIfx,right,0,7);
4910             break;
4911
4912           default:
4913             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4914             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4915             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4916             rFalseIfx.condition ^= 1;
4917             if (AOP_TYPE(result) == AOP_CRY)
4918               genSkipc(&rFalseIfx);
4919             else {
4920               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4921               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4922             }         
4923             break;
4924           }
4925         }
4926
4927         if(ifx) ifx->generated = 1;
4928         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4929                 goto check_carry;
4930         return;
4931
4932       } else {
4933
4934         /* Size is greater than 1 */
4935
4936         if(sign) {
4937           int lp1 = lit+1;
4938
4939           size--;
4940
4941           if(lp1 == 0) {
4942             /* this means lit = 0xffffffff, or -1 */
4943
4944
4945             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4946             rFalseIfx.condition ^= 1;
4947             genSkipCond(&rFalseIfx,right,size,7);
4948             if(ifx) ifx->generated = 1;
4949             return;
4950           }
4951
4952           if(lit == 0) {
4953             int s = size;
4954
4955             if(rFalseIfx.condition) {
4956               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4957               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4958             }
4959
4960             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4961             while(size--)
4962               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4963
4964
4965             emitSKPZ;
4966             if(rFalseIfx.condition) {
4967               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4968               pic16_emitpLabel(truelbl->key);
4969             }else {
4970               rFalseIfx.condition ^= 1;
4971               genSkipCond(&rFalseIfx,right,s,7);
4972             }
4973
4974             if(ifx) ifx->generated = 1;
4975             return;
4976           }
4977
4978           if((size == 1) &&  (0 == (lp1&0xff))) {
4979             /* lower byte of signed word is zero */
4980             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4981             i = ((lp1 >> 8) & 0xff) ^0x80;
4982             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4983             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4984             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4985             rFalseIfx.condition ^= 1;
4986             genSkipc(&rFalseIfx);
4987
4988
4989             if(ifx) ifx->generated = 1;
4990             return;
4991           }
4992
4993           if(lit & (0x80 << (size*8))) {
4994             /* Lit is less than zero */
4995             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4996             //rFalseIfx.condition ^= 1;
4997             //genSkipCond(&rFalseIfx,left,size,7);
4998             //rFalseIfx.condition ^= 1;
4999             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5000             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5001
5002             if(rFalseIfx.condition)
5003               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5004             else
5005               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5006
5007
5008           } else {
5009             /* Lit is greater than or equal to zero */
5010             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5011             //rFalseIfx.condition ^= 1;
5012             //genSkipCond(&rFalseIfx,right,size,7);
5013             //rFalseIfx.condition ^= 1;
5014
5015             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5016             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5017
5018             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5019             if(rFalseIfx.condition)
5020               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5021             else
5022               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5023
5024           }
5025
5026
5027           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5028           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5029
5030           while(size--) {
5031
5032             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5033             emitSKPNZ;
5034             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5035           }
5036           rFalseIfx.condition ^= 1;
5037           //rFalseIfx.condition = 1;
5038           genSkipc(&rFalseIfx);
5039
5040           pic16_emitpLabel(truelbl->key);
5041
5042           if(ifx) ifx->generated = 1;
5043           return;
5044           // end of if (sign)
5045         } else {
5046
5047           /* compare word or long to an unsigned literal on the right.*/
5048
5049
5050           size--;
5051           if(lit < 0xff) {
5052             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5053             switch (lit) {
5054             case 0:
5055               break; /* handled above */
5056 /*
5057             case 0xff:
5058               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5059               while(size--)
5060                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5061               genSkipz2(&rFalseIfx,0);
5062               break;
5063 */
5064             default:
5065               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5066               while(--size)
5067                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5068
5069               emitSKPZ;
5070               if(rFalseIfx.condition)
5071                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5072               else
5073                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5074
5075
5076               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5077               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5078
5079               rFalseIfx.condition ^= 1;
5080               genSkipc(&rFalseIfx);
5081             }
5082
5083             pic16_emitpLabel(truelbl->key);
5084
5085             if(ifx) ifx->generated = 1;
5086             return;
5087           }
5088
5089
5090           lit++;
5091           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5092           i = (lit >> (size*8)) & 0xff;
5093
5094           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5095           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5096
5097           while(size--) {
5098             i = (lit >> (size*8)) & 0xff;
5099
5100             if(i) {
5101               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5102               emitSKPNZ;
5103               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5104             } else {
5105               /* this byte of the lit is zero, 
5106                * if it's not the last then OR in the variable */
5107               if(size)
5108                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5109             }
5110           }
5111
5112
5113           pic16_emitpLabel(lbl->key);
5114
5115           rFalseIfx.condition ^= 1;
5116
5117           genSkipc(&rFalseIfx);
5118         }
5119
5120         if(sign)
5121           pic16_emitpLabel(truelbl->key);
5122         if(ifx) ifx->generated = 1;
5123         return;
5124       }
5125     }
5126     /* Compare two variables */
5127
5128     DEBUGpic16_emitcode(";sign","%d",sign);
5129
5130     size--;
5131     if(sign) {
5132       /* Sigh. thus sucks... */
5133       if(size) {
5134         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5135         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5136         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5137         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5138         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5139         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5140       } else {
5141         /* Signed char comparison */
5142         /* Special thanks to Nikolai Golovchenko for this snippet */
5143         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5144         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5145         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5146         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5147         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5148         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5149
5150         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5151         genSkipc(&rFalseIfx);
5152           
5153         if(ifx) ifx->generated = 1;
5154         return;
5155       }
5156
5157     } else {
5158
5159       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5160       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5161     }
5162
5163
5164     /* The rest of the bytes of a multi-byte compare */
5165     while (size) {
5166
5167       emitSKPZ;
5168       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5169       size--;
5170
5171       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5172       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5173
5174
5175     }
5176
5177     pic16_emitpLabel(lbl->key);
5178
5179     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5180     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5181         (AOP_TYPE(result) == AOP_REG)) {
5182       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5183       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5184     } else {
5185       genSkipc(&rFalseIfx);
5186     }         
5187     //genSkipc(&rFalseIfx);
5188     if(ifx) ifx->generated = 1;
5189
5190     return;
5191
5192   }
5193
5194 check_carry:
5195   if ((AOP_TYPE(result) != AOP_CRY) 
5196         && AOP_SIZE(result)) {
5197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5198 //    pic16_emitpLabel( rFalseIfx.lbl->key );
5199
5200     pic16_outBitC(result);
5201   } else {
5202     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5203     /* if the result is used in the next
5204        ifx conditional branch then generate
5205        code a little differently */
5206     if (ifx )
5207       genIfxJump (ifx,"c");
5208     else
5209       pic16_outBitC(result);
5210     /* leave the result in acc */
5211   }
5212
5213 }
5214
5215 /*-----------------------------------------------------------------*/
5216 /* genCmpGt :- greater than comparison                             */
5217 /*-----------------------------------------------------------------*/
5218 static void genCmpGt (iCode *ic, iCode *ifx)
5219 {
5220     operand *left, *right, *result;
5221     sym_link *letype , *retype;
5222     int sign ;
5223
5224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5225     left = IC_LEFT(ic);
5226     right= IC_RIGHT(ic);
5227     result = IC_RESULT(ic);
5228
5229     letype = getSpec(operandType(left));
5230     retype =getSpec(operandType(right));
5231     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5232     /* assign the amsops */
5233     pic16_aopOp (left,ic,FALSE);
5234     pic16_aopOp (right,ic,FALSE);
5235     pic16_aopOp (result,ic,TRUE);
5236
5237     genCmp(right, left, result, ifx, sign);
5238
5239     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5240     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5241     pic16_freeAsmop(result,NULL,ic,TRUE); 
5242 }
5243
5244 /*-----------------------------------------------------------------*/
5245 /* genCmpLt - less than comparisons                                */
5246 /*-----------------------------------------------------------------*/
5247 static void genCmpLt (iCode *ic, iCode *ifx)
5248 {
5249     operand *left, *right, *result;
5250     sym_link *letype , *retype;
5251     int sign ;
5252
5253     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5254     left = IC_LEFT(ic);
5255     right= IC_RIGHT(ic);
5256     result = IC_RESULT(ic);
5257
5258     letype = getSpec(operandType(left));
5259     retype =getSpec(operandType(right));
5260     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5261
5262     /* assign the amsops */
5263     pic16_aopOp (left,ic,FALSE);
5264     pic16_aopOp (right,ic,FALSE);
5265     pic16_aopOp (result,ic,TRUE);
5266
5267     genCmp(left, right, result, ifx, sign);
5268
5269     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5270     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5271     pic16_freeAsmop(result,NULL,ic,TRUE); 
5272 }
5273
5274 #if 0
5275 // not needed ATM
5276 // FIXME reenable literal optimisation when the pic16 port is stable
5277
5278 /*-----------------------------------------------------------------*/
5279 /* genc16bit2lit - compare a 16 bit value to a literal             */
5280 /*-----------------------------------------------------------------*/
5281 static void genc16bit2lit(operand *op, int lit, int offset)
5282 {
5283   int i;
5284
5285   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5286   if( (lit&0xff) == 0) 
5287     i=1;
5288   else
5289     i=0;
5290
5291   switch( BYTEofLONG(lit,i)) { 
5292   case 0:
5293     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5294     break;
5295   case 1:
5296     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5297     break;
5298   case 0xff:
5299     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5300     break;
5301   default:
5302     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5303     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5304   }
5305
5306   i ^= 1;
5307
5308   switch( BYTEofLONG(lit,i)) { 
5309   case 0:
5310     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5311     break;
5312   case 1:
5313     emitSKPNZ;
5314     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5315     break;
5316   case 0xff:
5317     emitSKPNZ;
5318     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5319     break;
5320   default:
5321     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5322     emitSKPNZ;
5323     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5324
5325   }
5326
5327 }
5328 #endif
5329
5330 #if 0
5331 // not needed ATM
5332 /*-----------------------------------------------------------------*/
5333 /* gencjneshort - compare and jump if not equal                    */
5334 /*-----------------------------------------------------------------*/
5335 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5336 {
5337   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5338   int offset = 0;
5339   int res_offset = 0;  /* the result may be a different size then left or right */
5340   int res_size = AOP_SIZE(result);
5341   resolvedIfx rIfx;
5342   symbol *lbl, *lbl_done;
5343
5344   unsigned long lit = 0L;
5345   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5346
5347   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5348   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5349   if(result)
5350     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5351   resolveIfx(&rIfx,ifx);
5352   lbl =  newiTempLabel(NULL);
5353   lbl_done =  newiTempLabel(NULL);
5354
5355
5356   /* if the left side is a literal or 
5357      if the right is in a pointer register and left 
5358      is not */
5359   if ((AOP_TYPE(left) == AOP_LIT) || 
5360       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5361     operand *t = right;
5362     right = left;
5363     left = t;
5364   }
5365   if(AOP_TYPE(right) == AOP_LIT)
5366     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5367
5368   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5369     preserve_result = 1;
5370
5371   if(result && !preserve_result)
5372     {
5373       int i;
5374       for(i = 0; i < AOP_SIZE(result); i++)
5375         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5376     }
5377
5378
5379   /* if the right side is a literal then anything goes */
5380   if (AOP_TYPE(right) == AOP_LIT &&
5381       AOP_TYPE(left) != AOP_DIR ) {
5382     switch(size) {
5383     case 2:
5384       genc16bit2lit(left, lit, 0);
5385       emitSKPZ;
5386       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5387       break;
5388     default:
5389       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5390       while (size--) {
5391         if(lit & 0xff) {
5392           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5393           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5394         } else {
5395           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5396         }
5397
5398         emitSKPZ;
5399         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5400         offset++;
5401         if(res_offset < res_size-1)
5402           res_offset++;
5403         lit >>= 8;
5404       }
5405       break;
5406     }
5407   }
5408
5409   /* if the right side is in a register or in direct space or
5410      if the left is a pointer register & right is not */    
5411   else if (AOP_TYPE(right) == AOP_REG ||
5412            AOP_TYPE(right) == AOP_DIR || 
5413            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5414            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5415     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5416     int lbl_key = lbl->key;
5417
5418     if(result) {
5419       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5420       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5421     }else {
5422       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5423       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5424               __FUNCTION__,__LINE__);
5425       return;
5426     }
5427    
5428 /*     switch(size) { */
5429 /*     case 2: */
5430 /*       genc16bit2lit(left, lit, 0); */
5431 /*       emitSKPNZ; */
5432 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5433 /*       break; */
5434 /*     default: */
5435     while (size--) {
5436       int emit_skip=1;
5437       if((AOP_TYPE(left) == AOP_DIR) && 
5438          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5439
5440         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5441         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5442
5443       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5444             
5445         switch (lit & 0xff) {
5446         case 0:
5447           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5448           break;
5449         case 1:
5450           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5451           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5452           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5453           emit_skip=0;
5454           break;
5455         case 0xff:
5456           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5457           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5458           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5459           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5460           emit_skip=0;
5461           break;
5462         default:
5463           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5464           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5465         }
5466         lit >>= 8;
5467
5468       } else {
5469         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5470       }
5471       if(emit_skip) {
5472         if(AOP_TYPE(result) == AOP_CRY) {
5473           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5474           if(rIfx.condition)
5475             emitSKPNZ;
5476           else
5477             emitSKPZ;
5478           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5479         } else {
5480           /* fix me. probably need to check result size too */
5481           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5482           if(rIfx.condition)
5483             emitSKPZ;
5484           else
5485             emitSKPNZ;
5486           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5487           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5488         }
5489         if(ifx)
5490           ifx->generated=1;
5491       }
5492       emit_skip++;
5493       offset++;
5494       if(res_offset < res_size-1)
5495         res_offset++;
5496     }
5497 /*       break; */
5498 /*     } */
5499   } else if(AOP_TYPE(right) == AOP_REG &&
5500             AOP_TYPE(left) != AOP_DIR){
5501
5502     while(size--) {
5503       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5504       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5505       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5506       if(rIfx.condition)
5507         emitSKPNZ;
5508       else
5509         emitSKPZ;
5510       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5511       offset++;
5512       if(res_offset < res_size-1)
5513         res_offset++;
5514     }
5515       
5516   }else{
5517     /* right is a pointer reg need both a & b */
5518     while(size--) {
5519       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5520       if(strcmp(l,"b"))
5521         pic16_emitcode("mov","b,%s",l);
5522       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5523       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5524       offset++;
5525     }
5526   }
5527
5528   if(result && preserve_result)
5529     {
5530       int i;
5531       for(i = 0; i < AOP_SIZE(result); i++)
5532         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5533     }
5534
5535   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5536
5537   if(result && preserve_result)
5538     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5539
5540   if(!rIfx.condition)
5541     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5542
5543   pic16_emitpLabel(lbl->key);
5544
5545   if(result && preserve_result)
5546     {
5547       int i;
5548       for(i = 0; i < AOP_SIZE(result); i++)
5549         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5550
5551       pic16_emitpLabel(lbl_done->key);
5552    }
5553
5554   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5555
5556   if(ifx)
5557     ifx->generated = 1;
5558 }
5559 #endif
5560
5561 #if 0
5562 /*-----------------------------------------------------------------*/
5563 /* gencjne - compare and jump if not equal                         */
5564 /*-----------------------------------------------------------------*/
5565 static void gencjne(operand *left, operand *right, iCode *ifx)
5566 {
5567     symbol *tlbl  = newiTempLabel(NULL);
5568
5569     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5570     gencjneshort(left, right, lbl);
5571
5572     pic16_emitcode("mov","a,%s",one);
5573     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5574     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5575     pic16_emitcode("clr","a");
5576     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5577
5578     pic16_emitpLabel(lbl->key);
5579     pic16_emitpLabel(tlbl->key);
5580
5581 }
5582 #endif
5583
5584
5585 /*-----------------------------------------------------------------*/
5586 /* is_LitOp - check if operand has to be treated as literal        */
5587 /*-----------------------------------------------------------------*/
5588 static bool is_LitOp(operand *op)
5589 {
5590   return (AOP_TYPE(op) == AOP_LIT)
5591       || ( (AOP_TYPE(op) == AOP_PCODE)
5592           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5593               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5594 }
5595
5596 /*-----------------------------------------------------------------*/
5597 /* is_LitAOp - check if operand has to be treated as literal        */
5598 /*-----------------------------------------------------------------*/
5599 static bool is_LitAOp(asmop *aop)
5600 {
5601   return (aop->type == AOP_LIT)
5602       || ( (aop->type == AOP_PCODE)
5603           && ( (aop->aopu.pcop->type == PO_LITERAL)
5604               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5605 }
5606
5607
5608
5609 /*-----------------------------------------------------------------*/
5610 /* genCmpEq - generates code for equal to                          */
5611 /*-----------------------------------------------------------------*/
5612 static void genCmpEq (iCode *ic, iCode *ifx)
5613 {
5614   operand *left, *right, *result;
5615   symbol *falselbl = newiTempLabel(NULL);
5616   symbol *donelbl = newiTempLabel(NULL);
5617
5618   int preserve_result = 0;
5619   int generate_result = 0;
5620   int i=0;
5621
5622   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5623   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5624   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5625  
5626   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5627   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5628
5629   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5630     {
5631       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5632       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5633       goto release;
5634     }
5635
5636   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5637     {
5638       operand *tmp = right ;
5639       right = left;
5640       left = tmp;
5641     }
5642
5643   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5644     preserve_result = 1;
5645
5646   if(result && AOP_SIZE(result))
5647     generate_result = 1;
5648
5649   if(generate_result && !preserve_result)
5650     {
5651       for(i = 0; i < AOP_SIZE(result); i++)
5652         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5653     }
5654
5655   for(i=0; i < AOP_SIZE(left); i++)
5656     {
5657       if(AOP_TYPE(left) != AOP_ACC)
5658         {
5659           if(is_LitOp(left))
5660             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5661           else
5662             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5663         }
5664       if(is_LitOp(right))
5665         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5666       else
5667         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5668
5669       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5670     }
5671
5672   // result == true
5673
5674   if(generate_result && preserve_result)
5675     {
5676       for(i = 0; i < AOP_SIZE(result); i++)
5677         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5678     }
5679
5680   if(generate_result)
5681     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5682
5683   if(generate_result && preserve_result)
5684     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5685
5686   if(ifx && IC_TRUE(ifx))
5687     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5688
5689   if(ifx && IC_FALSE(ifx))
5690     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5691
5692   pic16_emitpLabel(falselbl->key);
5693
5694   // result == false
5695
5696   if(ifx && IC_FALSE(ifx))
5697     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5698
5699   if(generate_result && preserve_result)
5700     {
5701       for(i = 0; i < AOP_SIZE(result); i++)
5702         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5703     }
5704
5705   pic16_emitpLabel(donelbl->key);
5706
5707   if(ifx)
5708     ifx->generated = 1;
5709
5710 release:
5711   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5712   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5713   pic16_freeAsmop(result,NULL,ic,TRUE);
5714
5715 }
5716
5717
5718 #if 0
5719 // old version kept for reference
5720
5721 /*-----------------------------------------------------------------*/
5722 /* genCmpEq - generates code for equal to                          */
5723 /*-----------------------------------------------------------------*/
5724 static void genCmpEq (iCode *ic, iCode *ifx)
5725 {
5726     operand *left, *right, *result;
5727     unsigned long lit = 0L;
5728     int size,offset=0;
5729     symbol *falselbl  = newiTempLabel(NULL);
5730
5731
5732     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5733
5734     if(ifx)
5735       DEBUGpic16_emitcode ("; ifx is non-null","");
5736     else
5737       DEBUGpic16_emitcode ("; ifx is null","");
5738
5739     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5740     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5741     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5742
5743     size = max(AOP_SIZE(left),AOP_SIZE(right));
5744
5745     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5746
5747     /* if literal, literal on the right or 
5748     if the right is in a pointer register and left 
5749     is not */
5750     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5751         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5752       operand *tmp = right ;
5753       right = left;
5754       left = tmp;
5755     }
5756
5757
5758     if(ifx && !AOP_SIZE(result)){
5759         symbol *tlbl;
5760         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5761         /* if they are both bit variables */
5762         if (AOP_TYPE(left) == AOP_CRY &&
5763             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5764                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5765             if(AOP_TYPE(right) == AOP_LIT){
5766                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5767                 if(lit == 0L){
5768                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5769                     pic16_emitcode("cpl","c");
5770                 } else if(lit == 1L) {
5771                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5772                 } else {
5773                     pic16_emitcode("clr","c");
5774                 }
5775                 /* AOP_TYPE(right) == AOP_CRY */
5776             } else {
5777                 symbol *lbl = newiTempLabel(NULL);
5778                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5779                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5780                 pic16_emitcode("cpl","c");
5781                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5782             }
5783             /* if true label then we jump if condition
5784             supplied is true */
5785             tlbl = newiTempLabel(NULL);
5786             if ( IC_TRUE(ifx) ) {
5787                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5788                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5789             } else {
5790                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5791                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5792             }
5793             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5794
5795                 {
5796                 /* left and right are both bit variables, result is carry */
5797                         resolvedIfx rIfx;
5798               
5799                         resolveIfx(&rIfx,ifx);
5800
5801                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5802                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5803                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5804                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5805                         genSkipz2(&rIfx,0);
5806                 }
5807         } else {
5808
5809                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5810
5811                         /* They're not both bit variables. Is the right a literal? */
5812                         if(AOP_TYPE(right) == AOP_LIT) {
5813                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5814             
5815                         switch(size) {
5816
5817                                 case 1:
5818                                         switch(lit & 0xff) {
5819                                                 case 1:
5820                                                                 if ( IC_TRUE(ifx) ) {
5821                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5822                                                                         emitSKPNZ;
5823                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5824                                                                 } else {
5825                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5826                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5827                                                                 }
5828                                                                 break;
5829                                                 case 0xff:
5830                                                                 if ( IC_TRUE(ifx) ) {
5831                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5832                                                                         emitSKPNZ;
5833                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5834                                                                 } else {
5835                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5836                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5837                                                                 }
5838                                                                 break;
5839                                                 default:
5840                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5841                                                                 if(lit)
5842                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5843                                                                 genSkip(ifx,'z');
5844                                         } // switch lit
5845
5846
5847                                         /* end of size == 1 */
5848                                         break;
5849               
5850                                 case 2:
5851                                         genc16bit2lit(left,lit,offset);
5852                                         genSkip(ifx,'z');
5853                                         break;
5854                                         /* end of size == 2 */
5855
5856                                 default:
5857                                         /* size is 4 */
5858                                         if(lit==0) {
5859                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5860                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5861                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5862                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5863                                                 genSkip(ifx,'z');
5864                                         } else {
5865                                                 /* search for patterns that can be optimized */
5866
5867                                                 genc16bit2lit(left,lit,0);
5868                                                 lit >>= 16;
5869                                                 if(lit) {
5870                                                                 if(IC_TRUE(ifx))
5871                                                                 emitSKPZ; // if hi word unequal
5872                                                                 else
5873                                                                 emitSKPNZ; // if hi word equal
5874                                                                 // fail early
5875                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5876                                                         genc16bit2lit(left,lit,2);
5877                                                         genSkip(ifx,'z');
5878                                                 } else {
5879                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5880                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5881                                                         genSkip(ifx,'z');
5882                                                 }
5883                                         }
5884                                                 pic16_emitpLabel(falselbl->key);
5885                                                 break;
5886
5887                         } // switch size
5888           
5889                         ifx->generated = 1;
5890                         goto release ;
5891             
5892
5893           } else if(AOP_TYPE(right) == AOP_CRY ) {
5894             /* we know the left is not a bit, but that the right is */
5895             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5896             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5897                       pic16_popGet(AOP(right),offset));
5898             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5899
5900             /* if the two are equal, then W will be 0 and the Z bit is set
5901              * we could test Z now, or go ahead and check the high order bytes if
5902              * the variable we're comparing is larger than a byte. */
5903
5904             while(--size)
5905               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5906
5907             if ( IC_TRUE(ifx) ) {
5908               emitSKPNZ;
5909               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5910               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5911             } else {
5912               emitSKPZ;
5913               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5914               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5915             }
5916
5917           } else {
5918             /* They're both variables that are larger than bits */
5919             int s = size;
5920
5921             tlbl = newiTempLabel(NULL);
5922
5923             while(size--) {
5924               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5925               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5926
5927               if ( IC_TRUE(ifx) ) {
5928                 if(size) {
5929                   emitSKPZ;
5930                 
5931                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5932
5933                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5934                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5935                 } else {
5936                   emitSKPNZ;
5937
5938                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5939
5940
5941                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5942                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5943                 }
5944               } else {
5945                 emitSKPZ;
5946
5947                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5948
5949                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5950                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5951               }
5952               offset++;
5953             }
5954             if(s>1 && IC_TRUE(ifx)) {
5955               pic16_emitpLabel(tlbl->key);
5956               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5957             }
5958           }
5959         }
5960         /* mark the icode as generated */
5961         ifx->generated = 1;
5962         goto release ;
5963     }
5964
5965     /* if they are both bit variables */
5966     if (AOP_TYPE(left) == AOP_CRY &&
5967         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5968         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5969         if(AOP_TYPE(right) == AOP_LIT){
5970             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5971             if(lit == 0L){
5972                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5973                 pic16_emitcode("cpl","c");
5974             } else if(lit == 1L) {
5975                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5976             } else {
5977                 pic16_emitcode("clr","c");
5978             }
5979             /* AOP_TYPE(right) == AOP_CRY */
5980         } else {
5981             symbol *lbl = newiTempLabel(NULL);
5982             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5983             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5984             pic16_emitcode("cpl","c");
5985             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5986         }
5987         /* c = 1 if egal */
5988         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5989             pic16_outBitC(result);
5990             goto release ;
5991         }
5992         if (ifx) {
5993             genIfxJump (ifx,"c");
5994             goto release ;
5995         }
5996         /* if the result is used in an arithmetic operation
5997         then put the result in place */
5998         pic16_outBitC(result);
5999     } else {
6000       
6001       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6002       gencjne(left,right,result,ifx);
6003 /*
6004       if(ifx) 
6005         gencjne(left,right,newiTempLabel(NULL));
6006       else {
6007         if(IC_TRUE(ifx)->key)
6008           gencjne(left,right,IC_TRUE(ifx)->key);
6009         else
6010           gencjne(left,right,IC_FALSE(ifx)->key);
6011         ifx->generated = 1;
6012         goto release ;
6013       }
6014       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6015         pic16_aopPut(AOP(result),"a",0);
6016         goto release ;
6017       }
6018
6019       if (ifx) {
6020         genIfxJump (ifx,"a");
6021         goto release ;
6022       }
6023 */
6024       /* if the result is used in an arithmetic operation
6025          then put the result in place */
6026 /*
6027       if (AOP_TYPE(result) != AOP_CRY) 
6028         pic16_outAcc(result);
6029 */
6030       /* leave the result in acc */
6031     }
6032
6033 release:
6034     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6035     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6036     pic16_freeAsmop(result,NULL,ic,TRUE);
6037 }
6038 #endif
6039
6040 /*-----------------------------------------------------------------*/
6041 /* ifxForOp - returns the icode containing the ifx for operand     */
6042 /*-----------------------------------------------------------------*/
6043 static iCode *ifxForOp ( operand *op, iCode *ic )
6044 {
6045     /* if true symbol then needs to be assigned */
6046     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6047     if (IS_TRUE_SYMOP(op))
6048         return NULL ;
6049
6050     /* if this has register type condition and
6051     the next instruction is ifx with the same operand
6052     and live to of the operand is upto the ifx only then */
6053     if (ic->next
6054         && ic->next->op == IFX
6055         && IC_COND(ic->next)->key == op->key
6056         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6057         ) {
6058                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6059           return ic->next;
6060     }
6061
6062     if (ic->next &&
6063         ic->next->op == IFX &&
6064         IC_COND(ic->next)->key == op->key) {
6065       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6066       return ic->next;
6067     }
6068
6069     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6070     if (ic->next &&
6071         ic->next->op == IFX)
6072       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6073
6074     if (ic->next &&
6075         ic->next->op == IFX &&
6076         IC_COND(ic->next)->key == op->key) {
6077       DEBUGpic16_emitcode ("; "," key is okay");
6078       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6079                            OP_SYMBOL(op)->liveTo,
6080                            ic->next->seq);
6081     }
6082
6083 #if 0
6084     /* the code below is completely untested
6085      * it just allows ulong2fs.c compile -- VR */
6086          
6087     ic = ic->next;
6088     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6089                                         __FILE__, __FUNCTION__, __LINE__);
6090         
6091     /* if this has register type condition and
6092     the next instruction is ifx with the same operand
6093     and live to of the operand is upto the ifx only then */
6094     if (ic->next &&
6095         ic->next->op == IFX &&
6096         IC_COND(ic->next)->key == op->key &&
6097         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6098         return ic->next;
6099
6100     if (ic->next &&
6101         ic->next->op == IFX &&
6102         IC_COND(ic->next)->key == op->key) {
6103       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6104       return ic->next;
6105     }
6106
6107     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6108                                         __FILE__, __FUNCTION__, __LINE__);
6109
6110 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6111 #endif
6112
6113     return NULL;
6114 }
6115 /*-----------------------------------------------------------------*/
6116 /* genAndOp - for && operation                                     */
6117 /*-----------------------------------------------------------------*/
6118 static void genAndOp (iCode *ic)
6119 {
6120     operand *left,*right, *result;
6121 /*     symbol *tlbl; */
6122
6123     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6124     /* note here that && operations that are in an
6125     if statement are taken away by backPatchLabels
6126     only those used in arthmetic operations remain */
6127     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6128     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6129     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6130
6131     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6132
6133     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6134     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6135     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6136
6137     /* if both are bit variables */
6138 /*     if (AOP_TYPE(left) == AOP_CRY && */
6139 /*         AOP_TYPE(right) == AOP_CRY ) { */
6140 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6141 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6142 /*         pic16_outBitC(result); */
6143 /*     } else { */
6144 /*         tlbl = newiTempLabel(NULL); */
6145 /*         pic16_toBoolean(left);     */
6146 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6147 /*         pic16_toBoolean(right); */
6148 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6149 /*         pic16_outBitAcc(result); */
6150 /*     } */
6151
6152     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6153     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6154     pic16_freeAsmop(result,NULL,ic,TRUE);
6155 }
6156
6157
6158 /*-----------------------------------------------------------------*/
6159 /* genOrOp - for || operation                                      */
6160 /*-----------------------------------------------------------------*/
6161 /*
6162   tsd pic port -
6163   modified this code, but it doesn't appear to ever get called
6164 */
6165
6166 static void genOrOp (iCode *ic)
6167 {
6168     operand *left,*right, *result;
6169     symbol *tlbl;
6170
6171     /* note here that || operations that are in an
6172     if statement are taken away by backPatchLabels
6173     only those used in arthmetic operations remain */
6174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6175     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6176     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6177     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6178
6179     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6180
6181     /* if both are bit variables */
6182     if (AOP_TYPE(left) == AOP_CRY &&
6183         AOP_TYPE(right) == AOP_CRY ) {
6184       pic16_emitcode("clrc","");
6185       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6186                AOP(left)->aopu.aop_dir,
6187                AOP(left)->aopu.aop_dir);
6188       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6189                AOP(right)->aopu.aop_dir,
6190                AOP(right)->aopu.aop_dir);
6191       pic16_emitcode("setc","");
6192
6193     } else {
6194         tlbl = newiTempLabel(NULL);
6195         pic16_toBoolean(left);
6196         emitSKPZ;
6197         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6198         pic16_toBoolean(right);
6199         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6200
6201         pic16_outBitAcc(result);
6202     }
6203
6204     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6205     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6206     pic16_freeAsmop(result,NULL,ic,TRUE);            
6207 }
6208
6209 /*-----------------------------------------------------------------*/
6210 /* isLiteralBit - test if lit == 2^n                               */
6211 /*-----------------------------------------------------------------*/
6212 static int isLiteralBit(unsigned long lit)
6213 {
6214     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6215     0x100L,0x200L,0x400L,0x800L,
6216     0x1000L,0x2000L,0x4000L,0x8000L,
6217     0x10000L,0x20000L,0x40000L,0x80000L,
6218     0x100000L,0x200000L,0x400000L,0x800000L,
6219     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6220     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6221     int idx;
6222     
6223     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6224     for(idx = 0; idx < 32; idx++)
6225         if(lit == pw[idx])
6226             return idx+1;
6227     return 0;
6228 }
6229
6230 /*-----------------------------------------------------------------*/
6231 /* continueIfTrue -                                                */
6232 /*-----------------------------------------------------------------*/
6233 static void continueIfTrue (iCode *ic)
6234 {
6235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6236     if(IC_TRUE(ic))
6237         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6238     ic->generated = 1;
6239 }
6240
6241 /*-----------------------------------------------------------------*/
6242 /* jmpIfTrue -                                                     */
6243 /*-----------------------------------------------------------------*/
6244 static void jumpIfTrue (iCode *ic)
6245 {
6246     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6247     if(!IC_TRUE(ic))
6248         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6249     ic->generated = 1;
6250 }
6251
6252 /*-----------------------------------------------------------------*/
6253 /* jmpTrueOrFalse -                                                */
6254 /*-----------------------------------------------------------------*/
6255 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6256 {
6257     // ugly but optimized by peephole
6258     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6259     if(IC_TRUE(ic)){
6260         symbol *nlbl = newiTempLabel(NULL);
6261         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6262         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6263         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6264         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6265     }
6266     else{
6267         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6268         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6269     }
6270     ic->generated = 1;
6271 }
6272
6273 /*-----------------------------------------------------------------*/
6274 /* genAnd  - code for and                                          */
6275 /*-----------------------------------------------------------------*/
6276 static void genAnd (iCode *ic, iCode *ifx)
6277 {
6278   operand *left, *right, *result;
6279   int size, offset=0;  
6280   unsigned long lit = 0L;
6281   int bytelit = 0;
6282   resolvedIfx rIfx;
6283
6284
6285   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6286   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6287   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6288   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6289
6290   resolveIfx(&rIfx,ifx);
6291
6292   /* if left is a literal & right is not then exchange them */
6293   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6294       AOP_NEEDSACC(left)) {
6295     operand *tmp = right ;
6296     right = left;
6297     left = tmp;
6298   }
6299
6300   /* if result = right then exchange them */
6301   if(pic16_sameRegs(AOP(result),AOP(right))){
6302     operand *tmp = right ;
6303     right = left;
6304     left = tmp;
6305   }
6306
6307   /* if right is bit then exchange them */
6308   if (AOP_TYPE(right) == AOP_CRY &&
6309       AOP_TYPE(left) != AOP_CRY){
6310     operand *tmp = right ;
6311     right = left;
6312     left = tmp;
6313   }
6314   if(AOP_TYPE(right) == AOP_LIT)
6315     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6316
6317   size = AOP_SIZE(result);
6318
6319   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6320
6321   // if(bit & yy)
6322   // result = bit & yy;
6323   if (AOP_TYPE(left) == AOP_CRY){
6324     // c = bit & literal;
6325     if(AOP_TYPE(right) == AOP_LIT){
6326       if(lit & 1) {
6327         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6328           // no change
6329           goto release;
6330         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6331       } else {
6332         // bit(result) = 0;
6333         if(size && (AOP_TYPE(result) == AOP_CRY)){
6334           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6335           goto release;
6336         }
6337         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6338           jumpIfTrue(ifx);
6339           goto release;
6340         }
6341         pic16_emitcode("clr","c");
6342       }
6343     } else {
6344       if (AOP_TYPE(right) == AOP_CRY){
6345         // c = bit & bit;
6346         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6347         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6348       } else {
6349         // c = bit & val;
6350         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6351         // c = lsb
6352         pic16_emitcode("rrc","a");
6353         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6354       }
6355     }
6356     // bit = c
6357     // val = c
6358     if(size)
6359       pic16_outBitC(result);
6360     // if(bit & ...)
6361     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6362       genIfxJump(ifx, "c");           
6363     goto release ;
6364   }
6365
6366   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6367   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6368   if((AOP_TYPE(right) == AOP_LIT) &&
6369      (AOP_TYPE(result) == AOP_CRY) &&
6370      (AOP_TYPE(left) != AOP_CRY)){
6371     int posbit = isLiteralBit(lit);
6372     /* left &  2^n */
6373     if(posbit){
6374       posbit--;
6375       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6376       // bit = left & 2^n
6377       if(size)
6378         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6379       // if(left &  2^n)
6380       else{
6381         if(ifx){
6382 /*
6383           if(IC_TRUE(ifx)) {
6384             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6385             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6386           } else {
6387             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6388             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6389           }
6390 */
6391         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6392         size = AOP_SIZE(left);
6393
6394         {
6395           int bp = posbit, ofs=0;
6396           
6397             while(bp > 7) {
6398               bp -= 8;
6399               ofs++;
6400             }
6401         
6402           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6403                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6404
6405         }
6406 /*
6407           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6408                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6409 */
6410           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6411           
6412           ifx->generated = 1;
6413         }
6414         goto release;
6415       }
6416     } else {
6417       symbol *tlbl = newiTempLabel(NULL);
6418       int sizel = AOP_SIZE(left);
6419       if(size)
6420         pic16_emitcode("setb","c");
6421       while(sizel--){
6422         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6423           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6424           // byte ==  2^n ?
6425           if((posbit = isLiteralBit(bytelit)) != 0)
6426             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6427           else{
6428             if(bytelit != 0x0FFL)
6429               pic16_emitcode("anl","a,%s",
6430                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6431             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6432           }
6433         }
6434         offset++;
6435       }
6436       // bit = left & literal
6437       if(size){
6438         pic16_emitcode("clr","c");
6439         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6440       }
6441       // if(left & literal)
6442       else{
6443         if(ifx)
6444           jmpTrueOrFalse(ifx, tlbl);
6445         goto release ;
6446       }
6447     }
6448     pic16_outBitC(result);
6449     goto release ;
6450   }
6451
6452   /* if left is same as result */
6453   if(pic16_sameRegs(AOP(result),AOP(left))){
6454     int know_W = -1;
6455     for(;size--; offset++,lit>>=8) {
6456       if(AOP_TYPE(right) == AOP_LIT){
6457         switch(lit & 0xff) {
6458         case 0x00:
6459           /*  and'ing with 0 has clears the result */
6460 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6461           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6462           break;
6463         case 0xff:
6464           /* and'ing with 0xff is a nop when the result and left are the same */
6465           break;
6466
6467         default:
6468           {
6469             int p = my_powof2( (~lit) & 0xff );
6470             if(p>=0) {
6471               /* only one bit is set in the literal, so use a bcf instruction */
6472 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6473               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6474
6475             } else {
6476               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6477               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6478               if(know_W != (lit&0xff))
6479                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6480               know_W = lit &0xff;
6481               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6482             }
6483           }    
6484         }
6485       } else {
6486         if (AOP_TYPE(left) == AOP_ACC) {
6487           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6488         } else {                    
6489           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6490           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6491
6492         }
6493       }
6494     }
6495
6496   } else {
6497     // left & result in different registers
6498     if(AOP_TYPE(result) == AOP_CRY){
6499       // result = bit
6500       // if(size), result in bit
6501       // if(!size && ifx), conditional oper: if(left & right)
6502       symbol *tlbl = newiTempLabel(NULL);
6503       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6504       if(size)
6505         pic16_emitcode("setb","c");
6506       while(sizer--){
6507         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6508         pic16_emitcode("anl","a,%s",
6509                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6510         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6511         offset++;
6512       }
6513       if(size){
6514         CLRC;
6515         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6516         pic16_outBitC(result);
6517       } else if(ifx)
6518         jmpTrueOrFalse(ifx, tlbl);
6519     } else {
6520       for(;(size--);offset++) {
6521         // normal case
6522         // result = left & right
6523         if(AOP_TYPE(right) == AOP_LIT){
6524           int t = (lit >> (offset*8)) & 0x0FFL;
6525           switch(t) { 
6526           case 0x00:
6527             pic16_emitcode("clrf","%s",
6528                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6529             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6530             break;
6531           case 0xff:
6532             pic16_emitcode("movf","%s,w",
6533                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6534             pic16_emitcode("movwf","%s",
6535                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6536             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6537             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6538             break;
6539           default:
6540             pic16_emitcode("movlw","0x%x",t);
6541             pic16_emitcode("andwf","%s,w",
6542                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6543             pic16_emitcode("movwf","%s",
6544                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6545               
6546             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6547             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6548             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6549           }
6550           continue;
6551         }
6552
6553         if (AOP_TYPE(left) == AOP_ACC) {
6554           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6555           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6556         } else {
6557           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6558           pic16_emitcode("andwf","%s,w",
6559                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6560           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6561           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6562         }
6563         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6564         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6565       }
6566     }
6567   }
6568
6569   release :
6570     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6571   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6572   pic16_freeAsmop(result,NULL,ic,TRUE);     
6573 }
6574
6575 /*-----------------------------------------------------------------*/
6576 /* genOr  - code for or                                            */
6577 /*-----------------------------------------------------------------*/
6578 static void genOr (iCode *ic, iCode *ifx)
6579 {
6580     operand *left, *right, *result;
6581     int size, offset=0;
6582     unsigned long lit = 0L;
6583
6584     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6585
6586     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6587     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6588     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6589
6590     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6591
6592     /* if left is a literal & right is not then exchange them */
6593     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6594         AOP_NEEDSACC(left)) {
6595         operand *tmp = right ;
6596         right = left;
6597         left = tmp;
6598     }
6599
6600     /* if result = right then exchange them */
6601     if(pic16_sameRegs(AOP(result),AOP(right))){
6602         operand *tmp = right ;
6603         right = left;
6604         left = tmp;
6605     }
6606
6607     /* if right is bit then exchange them */
6608     if (AOP_TYPE(right) == AOP_CRY &&
6609         AOP_TYPE(left) != AOP_CRY){
6610         operand *tmp = right ;
6611         right = left;
6612         left = tmp;
6613     }
6614
6615     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6616
6617     if(AOP_TYPE(right) == AOP_LIT)
6618         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6619
6620     size = AOP_SIZE(result);
6621
6622     // if(bit | yy)
6623     // xx = bit | yy;
6624     if (AOP_TYPE(left) == AOP_CRY){
6625         if(AOP_TYPE(right) == AOP_LIT){
6626             // c = bit & literal;
6627             if(lit){
6628                 // lit != 0 => result = 1
6629                 if(AOP_TYPE(result) == AOP_CRY){
6630                   if(size)
6631                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6632                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6633                   //     AOP(result)->aopu.aop_dir,
6634                   //     AOP(result)->aopu.aop_dir);
6635                     else if(ifx)
6636                         continueIfTrue(ifx);
6637                     goto release;
6638                 }
6639             } else {
6640                 // lit == 0 => result = left
6641                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6642                     goto release;
6643                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6644             }
6645         } else {
6646             if (AOP_TYPE(right) == AOP_CRY){
6647               if(pic16_sameRegs(AOP(result),AOP(left))){
6648                 // c = bit | bit;
6649                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6650                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6651                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6652
6653                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6654                          AOP(result)->aopu.aop_dir,
6655                          AOP(result)->aopu.aop_dir);
6656                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6657                          AOP(right)->aopu.aop_dir,
6658                          AOP(right)->aopu.aop_dir);
6659                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6660                          AOP(result)->aopu.aop_dir,
6661                          AOP(result)->aopu.aop_dir);
6662               } else {
6663                 if( AOP_TYPE(result) == AOP_ACC) {
6664                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6665                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6666                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6667                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6668
6669                 } else {
6670
6671                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6672                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6673                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6674                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6675
6676                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6677                                  AOP(result)->aopu.aop_dir,
6678                                  AOP(result)->aopu.aop_dir);
6679                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6680                                  AOP(right)->aopu.aop_dir,
6681                                  AOP(right)->aopu.aop_dir);
6682                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6683                                  AOP(left)->aopu.aop_dir,
6684                                  AOP(left)->aopu.aop_dir);
6685                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6686                                  AOP(result)->aopu.aop_dir,
6687                                  AOP(result)->aopu.aop_dir);
6688                 }
6689               }
6690             } else {
6691                 // c = bit | val;
6692                 symbol *tlbl = newiTempLabel(NULL);
6693                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6694
6695
6696                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6697                 if( AOP_TYPE(right) == AOP_ACC) {
6698                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6699                   emitSKPNZ;
6700                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6701                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6702                 }
6703
6704
6705
6706                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6707                     pic16_emitcode(";XXX setb","c");
6708                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6709                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6710                 pic16_toBoolean(right);
6711                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6712                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6713                     jmpTrueOrFalse(ifx, tlbl);
6714                     goto release;
6715                 } else {
6716                     CLRC;
6717                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6718                 }
6719             }
6720         }
6721         // bit = c
6722         // val = c
6723         if(size)
6724             pic16_outBitC(result);
6725         // if(bit | ...)
6726         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6727             genIfxJump(ifx, "c");           
6728         goto release ;
6729     }
6730
6731     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6732     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6733     if((AOP_TYPE(right) == AOP_LIT) &&
6734        (AOP_TYPE(result) == AOP_CRY) &&
6735        (AOP_TYPE(left) != AOP_CRY)){
6736         if(lit){
6737           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6738             // result = 1
6739             if(size)
6740                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6741             else 
6742                 continueIfTrue(ifx);
6743             goto release;
6744         } else {
6745           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6746             // lit = 0, result = boolean(left)
6747             if(size)
6748                 pic16_emitcode(";XXX setb","c");
6749             pic16_toBoolean(right);
6750             if(size){
6751                 symbol *tlbl = newiTempLabel(NULL);
6752                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6753                 CLRC;
6754                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6755             } else {
6756                 genIfxJump (ifx,"a");
6757                 goto release;
6758             }
6759         }
6760         pic16_outBitC(result);
6761         goto release ;
6762     }
6763
6764     /* if left is same as result */
6765     if(pic16_sameRegs(AOP(result),AOP(left))){
6766       int know_W = -1;
6767       for(;size--; offset++,lit>>=8) {
6768         if(AOP_TYPE(right) == AOP_LIT){
6769           if((lit & 0xff) == 0)
6770             /*  or'ing with 0 has no effect */
6771             continue;
6772           else {
6773             int p = my_powof2(lit & 0xff);
6774             if(p>=0) {
6775               /* only one bit is set in the literal, so use a bsf instruction */
6776               pic16_emitpcode(POC_BSF,
6777                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6778             } else {
6779               if(know_W != (lit & 0xff))
6780                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6781               know_W = lit & 0xff;
6782               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6783             }
6784                     
6785           }
6786         } else {
6787           if (AOP_TYPE(left) == AOP_ACC) {
6788             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6789             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6790           } else {                  
6791             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6792             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6793
6794             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6795             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6796
6797           }
6798         }
6799       }
6800     } else {
6801         // left & result in different registers
6802         if(AOP_TYPE(result) == AOP_CRY){
6803             // result = bit
6804             // if(size), result in bit
6805             // if(!size && ifx), conditional oper: if(left | right)
6806             symbol *tlbl = newiTempLabel(NULL);
6807             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6808             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6809
6810
6811             if(size)
6812                 pic16_emitcode(";XXX setb","c");
6813             while(sizer--){
6814                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6815                 pic16_emitcode(";XXX orl","a,%s",
6816                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6817                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6818                 offset++;
6819             }
6820             if(size){
6821                 CLRC;
6822                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6823                 pic16_outBitC(result);
6824             } else if(ifx)
6825                 jmpTrueOrFalse(ifx, tlbl);
6826         } else for(;(size--);offset++){
6827           // normal case
6828           // result = left & right
6829           if(AOP_TYPE(right) == AOP_LIT){
6830             int t = (lit >> (offset*8)) & 0x0FFL;
6831             switch(t) { 
6832             case 0x00:
6833               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6834               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6835
6836               pic16_emitcode("movf","%s,w",
6837                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6838               pic16_emitcode("movwf","%s",
6839                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6840               break;
6841             default:
6842               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6843               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6844               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6845
6846               pic16_emitcode("movlw","0x%x",t);
6847               pic16_emitcode("iorwf","%s,w",
6848                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6849               pic16_emitcode("movwf","%s",
6850                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6851               
6852             }
6853             continue;
6854           }
6855
6856           // faster than result <- left, anl result,right
6857           // and better if result is SFR
6858           if (AOP_TYPE(left) == AOP_ACC) {
6859             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6860             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6861           } else {
6862             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6863             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6864
6865             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6866             pic16_emitcode("iorwf","%s,w",
6867                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6868           }
6869           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6870           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6871         }
6872     }
6873
6874 release :
6875     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6876     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6877     pic16_freeAsmop(result,NULL,ic,TRUE);     
6878 }
6879
6880 /*-----------------------------------------------------------------*/
6881 /* genXor - code for xclusive or                                   */
6882 /*-----------------------------------------------------------------*/
6883 static void genXor (iCode *ic, iCode *ifx)
6884 {
6885   operand *left, *right, *result;
6886   int size, offset=0;
6887   unsigned long lit = 0L;
6888
6889   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6890
6891   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6892   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6893   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6894
6895   /* if left is a literal & right is not ||
6896      if left needs acc & right does not */
6897   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6898       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6899     operand *tmp = right ;
6900     right = left;
6901     left = tmp;
6902   }
6903
6904   /* if result = right then exchange them */
6905   if(pic16_sameRegs(AOP(result),AOP(right))){
6906     operand *tmp = right ;
6907     right = left;
6908     left = tmp;
6909   }
6910
6911   /* if right is bit then exchange them */
6912   if (AOP_TYPE(right) == AOP_CRY &&
6913       AOP_TYPE(left) != AOP_CRY){
6914     operand *tmp = right ;
6915     right = left;
6916     left = tmp;
6917   }
6918   if(AOP_TYPE(right) == AOP_LIT)
6919     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6920
6921   size = AOP_SIZE(result);
6922
6923   // if(bit ^ yy)
6924   // xx = bit ^ yy;
6925   if (AOP_TYPE(left) == AOP_CRY){
6926     if(AOP_TYPE(right) == AOP_LIT){
6927       // c = bit & literal;
6928       if(lit>>1){
6929         // lit>>1  != 0 => result = 1
6930         if(AOP_TYPE(result) == AOP_CRY){
6931           if(size)
6932             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6933             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6934           else if(ifx)
6935             continueIfTrue(ifx);
6936           goto release;
6937         }
6938         pic16_emitcode("setb","c");
6939       } else{
6940         // lit == (0 or 1)
6941         if(lit == 0){
6942           // lit == 0, result = left
6943           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6944             goto release;
6945           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6946         } else{
6947           // lit == 1, result = not(left)
6948           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6949             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6950             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6951             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6952             goto release;
6953           } else {
6954             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6955             pic16_emitcode("cpl","c");
6956           }
6957         }
6958       }
6959
6960     } else {
6961       // right != literal
6962       symbol *tlbl = newiTempLabel(NULL);
6963       if (AOP_TYPE(right) == AOP_CRY){
6964         // c = bit ^ bit;
6965         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6966       }
6967       else{
6968         int sizer = AOP_SIZE(right);
6969         // c = bit ^ val
6970         // if val>>1 != 0, result = 1
6971         pic16_emitcode("setb","c");
6972         while(sizer){
6973           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6974           if(sizer == 1)
6975             // test the msb of the lsb
6976             pic16_emitcode("anl","a,#0xfe");
6977           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6978           sizer--;
6979         }
6980         // val = (0,1)
6981         pic16_emitcode("rrc","a");
6982       }
6983       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6984       pic16_emitcode("cpl","c");
6985       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6986     }
6987     // bit = c
6988     // val = c
6989     if(size)
6990       pic16_outBitC(result);
6991     // if(bit | ...)
6992     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6993       genIfxJump(ifx, "c");           
6994     goto release ;
6995   }
6996
6997   if(pic16_sameRegs(AOP(result),AOP(left))){
6998     /* if left is same as result */
6999     for(;size--; offset++) {
7000       if(AOP_TYPE(right) == AOP_LIT){
7001         int t  = (lit >> (offset*8)) & 0x0FFL;
7002         if(t == 0x00L)
7003           continue;
7004         else
7005           if (IS_AOP_PREG(left)) {
7006             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7007             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7008             pic16_aopPut(AOP(result),"a",offset);
7009           } else {
7010             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7011             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7012             pic16_emitcode("xrl","%s,%s",
7013                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7014                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7015           }
7016       } else {
7017         if (AOP_TYPE(left) == AOP_ACC)
7018           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7019         else {
7020           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7021           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7022 /*
7023           if (IS_AOP_PREG(left)) {
7024             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7025             pic16_aopPut(AOP(result),"a",offset);
7026           } else
7027             pic16_emitcode("xrl","%s,a",
7028                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7029 */
7030         }
7031       }
7032     }
7033   } else {
7034     // left & result in different registers
7035     if(AOP_TYPE(result) == AOP_CRY){
7036       // result = bit
7037       // if(size), result in bit
7038       // if(!size && ifx), conditional oper: if(left ^ right)
7039       symbol *tlbl = newiTempLabel(NULL);
7040       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7041       if(size)
7042         pic16_emitcode("setb","c");
7043       while(sizer--){
7044         if((AOP_TYPE(right) == AOP_LIT) &&
7045            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7046           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7047         } else {
7048           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7049           pic16_emitcode("xrl","a,%s",
7050                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7051         }
7052         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7053         offset++;
7054       }
7055       if(size){
7056         CLRC;
7057         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7058         pic16_outBitC(result);
7059       } else if(ifx)
7060         jmpTrueOrFalse(ifx, tlbl);
7061     } else for(;(size--);offset++){
7062       // normal case
7063       // result = left & right
7064       if(AOP_TYPE(right) == AOP_LIT){
7065         int t = (lit >> (offset*8)) & 0x0FFL;
7066         switch(t) { 
7067         case 0x00:
7068           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7069           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7070           pic16_emitcode("movf","%s,w",
7071                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7072           pic16_emitcode("movwf","%s",
7073                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7074           break;
7075         case 0xff:
7076           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7077           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7078           pic16_emitcode("comf","%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         default:
7084           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7085           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7086           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7087           pic16_emitcode("movlw","0x%x",t);
7088           pic16_emitcode("xorwf","%s,w",
7089                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7090           pic16_emitcode("movwf","%s",
7091                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7092
7093         }
7094         continue;
7095       }
7096
7097       // faster than result <- left, anl result,right
7098       // and better if result is SFR
7099       if (AOP_TYPE(left) == AOP_ACC) {
7100         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7101         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7102       } else {
7103         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7104         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7105         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7106         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7107       }
7108       if ( AOP_TYPE(result) != AOP_ACC){
7109         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7110         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7111       }
7112     }
7113   }
7114
7115   release :
7116     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7117   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7118   pic16_freeAsmop(result,NULL,ic,TRUE);     
7119 }
7120
7121 /*-----------------------------------------------------------------*/
7122 /* genInline - write the inline code out                           */
7123 /*-----------------------------------------------------------------*/
7124 static void genInline (iCode *ic)
7125 {
7126   char *buffer, *bp, *bp1;
7127     
7128         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7129
7130         _G.inLine += (!options.asmpeep);
7131
7132         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7133         strcpy(buffer,IC_INLINE(ic));
7134
7135 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7136
7137         /* emit each line as a code */
7138         while (*bp) {
7139                 if (*bp == '\n') {
7140                         *bp++ = '\0';
7141
7142                         if(*bp1)
7143                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7144                         bp1 = bp;
7145                 } else {
7146                         if (*bp == ':') {
7147                                 bp++;
7148                                 *bp = '\0';
7149                                 bp++;
7150
7151                                 /* print label, use this special format with NULL directive
7152                                  * to denote that the argument should not be indented with tab */
7153                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7154                                 bp1 = bp;
7155                         } else
7156                                 bp++;
7157                 }
7158         }
7159
7160         if ((bp1 != bp) && *bp1)
7161                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7162
7163
7164     Safe_free(buffer);
7165
7166     _G.inLine -= (!options.asmpeep);
7167 }
7168
7169 /*-----------------------------------------------------------------*/
7170 /* genRRC - rotate right with carry                                */
7171 /*-----------------------------------------------------------------*/
7172 static void genRRC (iCode *ic)
7173 {
7174   operand *left , *result ;
7175   int size, offset = 0, same;
7176
7177   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7178
7179   /* rotate right with carry */
7180   left = IC_LEFT(ic);
7181   result=IC_RESULT(ic);
7182   pic16_aopOp (left,ic,FALSE);
7183   pic16_aopOp (result,ic,FALSE);
7184
7185   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7186
7187   same = pic16_sameRegs(AOP(result),AOP(left));
7188
7189   size = AOP_SIZE(result);    
7190
7191   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7192
7193   /* get the lsb and put it into the carry */
7194   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7195
7196   offset = 0 ;
7197
7198   while(size--) {
7199
7200     if(same) {
7201       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7202     } else {
7203       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7204       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7205     }
7206
7207     offset++;
7208   }
7209
7210   pic16_freeAsmop(left,NULL,ic,TRUE);
7211   pic16_freeAsmop(result,NULL,ic,TRUE);
7212 }
7213
7214 /*-----------------------------------------------------------------*/
7215 /* genRLC - generate code for rotate left with carry               */
7216 /*-----------------------------------------------------------------*/
7217 static void genRLC (iCode *ic)
7218 {    
7219   operand *left , *result ;
7220   int size, offset = 0;
7221   int same;
7222
7223   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7224   /* rotate right with carry */
7225   left = IC_LEFT(ic);
7226   result=IC_RESULT(ic);
7227   pic16_aopOp (left,ic,FALSE);
7228   pic16_aopOp (result,ic,FALSE);
7229
7230   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7231
7232   same = pic16_sameRegs(AOP(result),AOP(left));
7233
7234   /* move it to the result */
7235   size = AOP_SIZE(result);    
7236
7237   /* get the msb and put it into the carry */
7238   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7239
7240   offset = 0 ;
7241
7242   while(size--) {
7243
7244     if(same) {
7245       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7246     } else {
7247       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7248       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7249     }
7250
7251     offset++;
7252   }
7253
7254
7255   pic16_freeAsmop(left,NULL,ic,TRUE);
7256   pic16_freeAsmop(result,NULL,ic,TRUE);
7257 }
7258
7259
7260 /* gpasm can get the highest order bit with HIGH/UPPER
7261  * so the following probably is not needed -- VR */
7262  
7263 /*-----------------------------------------------------------------*/
7264 /* genGetHbit - generates code get highest order bit               */
7265 /*-----------------------------------------------------------------*/
7266 static void genGetHbit (iCode *ic)
7267 {
7268     operand *left, *result;
7269     left = IC_LEFT(ic);
7270     result=IC_RESULT(ic);
7271     pic16_aopOp (left,ic,FALSE);
7272     pic16_aopOp (result,ic,FALSE);
7273
7274     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7275     /* get the highest order byte into a */
7276     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7277     if(AOP_TYPE(result) == AOP_CRY){
7278         pic16_emitcode("rlc","a");
7279         pic16_outBitC(result);
7280     }
7281     else{
7282         pic16_emitcode("rl","a");
7283         pic16_emitcode("anl","a,#0x01");
7284         pic16_outAcc(result);
7285     }
7286
7287
7288     pic16_freeAsmop(left,NULL,ic,TRUE);
7289     pic16_freeAsmop(result,NULL,ic,TRUE);
7290 }
7291
7292 #if 0
7293 /*-----------------------------------------------------------------*/
7294 /* AccRol - rotate left accumulator by known count                 */
7295 /*-----------------------------------------------------------------*/
7296 static void AccRol (int shCount)
7297 {
7298     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7299     shCount &= 0x0007;              // shCount : 0..7
7300     switch(shCount){
7301         case 0 :
7302             break;
7303         case 1 :
7304             pic16_emitcode("rl","a");
7305             break;
7306         case 2 :
7307             pic16_emitcode("rl","a");
7308             pic16_emitcode("rl","a");
7309             break;
7310         case 3 :
7311             pic16_emitcode("swap","a");
7312             pic16_emitcode("rr","a");
7313             break;
7314         case 4 :
7315             pic16_emitcode("swap","a");
7316             break;
7317         case 5 :
7318             pic16_emitcode("swap","a");
7319             pic16_emitcode("rl","a");
7320             break;
7321         case 6 :
7322             pic16_emitcode("rr","a");
7323             pic16_emitcode("rr","a");
7324             break;
7325         case 7 :
7326             pic16_emitcode("rr","a");
7327             break;
7328     }
7329 }
7330 #endif
7331
7332 /*-----------------------------------------------------------------*/
7333 /* AccLsh - left shift accumulator by known count                  */
7334 /*-----------------------------------------------------------------*/
7335 static void AccLsh (int shCount)
7336 {
7337         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7338         switch(shCount){
7339                 case 0 :
7340                         return;
7341                         break;
7342                 case 1 :
7343                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7344                         break;
7345                 case 2 :
7346                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7347                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7348                         break;
7349                 case 3 :
7350                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7351                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7352                         break;
7353                 case 4 :
7354                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7355                         break;
7356                 case 5 :
7357                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7358                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7359                         break;
7360                 case 6 :
7361                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7362                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7363                         break;
7364                 case 7 :
7365                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7366                         break;
7367         }
7368
7369         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7370 }
7371
7372 /*-----------------------------------------------------------------*/
7373 /* AccRsh - right shift accumulator by known count                 */
7374 /*-----------------------------------------------------------------*/
7375 static void AccRsh (int shCount, int andmask)
7376 {
7377         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7378         switch(shCount){
7379                 case 0 :
7380                         return; break;
7381                 case 1 :
7382                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7383 //                      andmask = 0;    /* no need */
7384                         break;
7385                 case 2 :
7386                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7387                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7388 //                      andmask = 0;    /* no need */
7389                         break;
7390                 case 3 :
7391                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7392                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7393                         break;
7394                 case 4 :
7395                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7396                         break;
7397                 case 5 :
7398                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7399                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7400                         break;
7401                 case 6 :
7402                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7403                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7404                         break;
7405                 case 7 :
7406                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7407                         break;
7408         }
7409         
7410         if(andmask)
7411                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7412         else
7413                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7414 }
7415
7416 #if 0
7417 /*-----------------------------------------------------------------*/
7418 /* AccSRsh - signed right shift accumulator by known count                 */
7419 /*-----------------------------------------------------------------*/
7420 static void AccSRsh (int shCount)
7421 {
7422     symbol *tlbl ;
7423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7424     if(shCount != 0){
7425         if(shCount == 1){
7426             pic16_emitcode("mov","c,acc.7");
7427             pic16_emitcode("rrc","a");
7428         } else if(shCount == 2){
7429             pic16_emitcode("mov","c,acc.7");
7430             pic16_emitcode("rrc","a");
7431             pic16_emitcode("mov","c,acc.7");
7432             pic16_emitcode("rrc","a");
7433         } else {
7434             tlbl = newiTempLabel(NULL);
7435             /* rotate right accumulator */
7436             AccRol(8 - shCount);
7437             /* and kill the higher order bits */
7438             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7439             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7440             pic16_emitcode("orl","a,#0x%02x",
7441                      (unsigned char)~SRMask[shCount]);
7442             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7443         }
7444     }
7445 }
7446 #endif
7447 /*-----------------------------------------------------------------*/
7448 /* shiftR1Left2Result - shift right one byte from left to result   */
7449 /*-----------------------------------------------------------------*/
7450 static void shiftR1Left2ResultSigned (operand *left, int offl,
7451                                 operand *result, int offr,
7452                                 int shCount)
7453 {
7454   int same;
7455
7456   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7457
7458   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7459
7460   switch(shCount) {
7461   case 1:
7462     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7463     if(same) 
7464       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7465     else {
7466       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7467       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7468     }
7469
7470     break;
7471   case 2:
7472
7473     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7474     if(same) 
7475       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7476     else {
7477       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7478       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7479     }
7480     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7481     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7482
7483     break;
7484
7485   case 3:
7486     if(same)
7487       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7488     else {
7489       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7490       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7491     }
7492
7493     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7494     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7495     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7496
7497     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7498     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7499
7500     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7501     break;
7502
7503   case 4:
7504     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7505     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7506     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7507     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7508     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7509     break;
7510   case 5:
7511     if(same) {
7512       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7513     } else {
7514       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7515       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7516     }
7517     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7518     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7519     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7520     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7521     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7522     break;
7523
7524   case 6:
7525     if(same) {
7526       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7527       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7528       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7529       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7530       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7531       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7532     } else {
7533       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7534       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7535       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7536       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7537       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7538     }
7539     break;
7540
7541   case 7:
7542     if(same) {
7543       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7544       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7545       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7546       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7547     } else {
7548       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7549       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7550       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7551     }
7552
7553   default:
7554     break;
7555   }
7556 }
7557
7558 /*-----------------------------------------------------------------*/
7559 /* shiftR1Left2Result - shift right one byte from left to result   */
7560 /*-----------------------------------------------------------------*/
7561 static void shiftR1Left2Result (operand *left, int offl,
7562                                 operand *result, int offr,
7563                                 int shCount, int sign)
7564 {
7565   int same;
7566
7567   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7568
7569   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7570
7571   /* Copy the msb into the carry if signed. */
7572   if(sign) {
7573     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7574     return;
7575   }
7576
7577
7578
7579   switch(shCount) {
7580   case 1:
7581     emitCLRC;
7582     if(same) 
7583       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7584     else {
7585       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7586       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7587     }
7588     break;
7589   case 2:
7590     emitCLRC;
7591     if(same) {
7592       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7593     } else {
7594       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7595       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7596     }
7597     emitCLRC;
7598     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7599
7600     break;
7601   case 3:
7602     if(same)
7603       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7604     else {
7605       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7606       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7607     }
7608
7609     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7610     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7611     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7612     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7613     break;
7614       
7615   case 4:
7616     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7617     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7618     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7619     break;
7620
7621   case 5:
7622     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7623     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7624     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7625     emitCLRC;
7626     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7627
7628     break;
7629   case 6:
7630
7631     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7632     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7633     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7634     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7635     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7636     break;
7637
7638   case 7:
7639
7640     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7641     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7642     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7643
7644     break;
7645
7646   default:
7647     break;
7648   }
7649 }
7650
7651 /*-----------------------------------------------------------------*/
7652 /* shiftL1Left2Result - shift left one byte from left to result    */
7653 /*-----------------------------------------------------------------*/
7654 static void shiftL1Left2Result (operand *left, int offl,
7655                                 operand *result, int offr, int shCount)
7656 {
7657   int same;
7658
7659   //    char *l;
7660   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7661
7662   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7663   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7664     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7665     //    MOVA(l);
7666     /* shift left accumulator */
7667     //AccLsh(shCount); // don't comment out just yet...
7668   //    pic16_aopPut(AOP(result),"a",offr);
7669
7670   switch(shCount) {
7671   case 1:
7672     /* Shift left 1 bit position */
7673     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7674     if(same) {
7675       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7676     } else {
7677       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7678       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7679     }
7680     break;
7681   case 2:
7682     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7683     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7684     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7685     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7686     break;
7687   case 3:
7688     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7689     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7690     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7691     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7692     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7693     break;
7694   case 4:
7695     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7696     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7697     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7698     break;
7699   case 5:
7700     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7701     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7702     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7703     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7704     break;
7705   case 6:
7706     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7707     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7708     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7709     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7710     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7711     break;
7712   case 7:
7713     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7714     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7715     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7716     break;
7717
7718   default:
7719     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7720   }
7721
7722 }
7723
7724 /*-----------------------------------------------------------------*/
7725 /* movLeft2Result - move byte from left to result                  */
7726 /*-----------------------------------------------------------------*/
7727 static void movLeft2Result (operand *left, int offl,
7728                             operand *result, int offr)
7729 {
7730   char *l;
7731   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7732   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7733     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7734
7735     if (*l == '@' && (IS_AOP_PREG(result))) {
7736       pic16_emitcode("mov","a,%s",l);
7737       pic16_aopPut(AOP(result),"a",offr);
7738     } else {
7739       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7740       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7741     }
7742   }
7743 }
7744
7745 /*-----------------------------------------------------------------*/
7746 /* shiftL2Left2Result - shift left two bytes from left to result   */
7747 /*-----------------------------------------------------------------*/
7748 static void shiftL2Left2Result (operand *left, int offl,
7749                                 operand *result, int offr, int shCount)
7750 {
7751   int same = pic16_sameRegs(AOP(result), AOP(left));
7752   int i;
7753
7754   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7755
7756   if (same && (offl != offr)) { // shift bytes
7757     if (offr > offl) {
7758        for(i=1;i>-1;i--) {
7759          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7760          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7761        }
7762     } else { // just treat as different later on
7763                 same = 0;
7764     }
7765   }
7766
7767   if(same) {
7768     switch(shCount) {
7769     case 0:
7770       break;
7771     case 1:
7772     case 2:
7773     case 3:
7774
7775       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7776       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7777       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7778
7779       while(--shCount) {
7780                 emitCLRC;
7781                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7782                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7783       }
7784
7785       break;
7786     case 4:
7787     case 5:
7788       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7789       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7790       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7791       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7792       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7793       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7794       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7795       if(shCount >=5) {
7796                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7797                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7798       }
7799       break;
7800     case 6:
7801       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7802       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7803       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7804       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7805       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7806       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7807       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7808       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7809       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7810       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7811       break;
7812     case 7:
7813       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7814       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7815       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7816       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7817       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7818     }
7819
7820   } else {
7821     switch(shCount) {
7822     case 0:
7823       break;
7824     case 1:
7825     case 2:
7826     case 3:
7827       /* note, use a mov/add for the shift since the mov has a
7828          chance of getting optimized out */
7829       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7830       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7831       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7832       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7833       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7834
7835       while(--shCount) {
7836                 emitCLRC;
7837                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7838                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7839       }
7840       break;
7841
7842     case 4:
7843     case 5:
7844       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7845       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7846       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7847       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7848       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7849       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7850       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7851       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7852
7853
7854       if(shCount == 5) {
7855                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7856                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7857       }
7858       break;
7859     case 6:
7860       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7861       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7862       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7863       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7864
7865       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7866       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7867       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7868       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7869       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7870       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7871       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7872       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7873       break;
7874     case 7:
7875       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7876       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7877       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7878       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7879       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7880     }
7881   }
7882
7883 }
7884 /*-----------------------------------------------------------------*/
7885 /* shiftR2Left2Result - shift right two bytes from left to result  */
7886 /*-----------------------------------------------------------------*/
7887 static void shiftR2Left2Result (operand *left, int offl,
7888                                 operand *result, int offr,
7889                                 int shCount, int sign)
7890 {
7891   int same = pic16_sameRegs(AOP(result), AOP(left));
7892   int i;
7893   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7894
7895   if (same && (offl != offr)) { // shift right bytes
7896     if (offr < offl) {
7897        for(i=0;i<2;i++) {
7898          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7899          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7900        }
7901     } else { // just treat as different later on
7902                 same = 0;
7903     }
7904   }
7905
7906   switch(shCount) {
7907   case 0:
7908     break;
7909   case 1:
7910   case 2:
7911   case 3:
7912     if(sign)
7913       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7914     else
7915       emitCLRC;
7916
7917     if(same) {
7918       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7919       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7920     } else {
7921       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7922       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7923       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7924       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7925     }
7926
7927     while(--shCount) {
7928       if(sign)
7929                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7930       else
7931                 emitCLRC;
7932       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7933       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7934     }
7935     break;
7936   case 4:
7937   case 5:
7938     if(same) {
7939
7940       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7941       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7942       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7943
7944       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7945       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7946       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7947       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7948     } else {
7949       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7950       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7951       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7952
7953       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7954       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7955       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7956       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7957       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7958     }
7959
7960     if(shCount >=5) {
7961       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7962       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7963     }
7964
7965     if(sign) {
7966       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7967       pic16_emitpcode(POC_BTFSC, 
7968                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7969       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7970     }
7971
7972     break;
7973
7974   case 6:
7975     if(same) {
7976
7977       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7978       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7979
7980       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7981       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7982       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7983       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7984       if(sign) {
7985         pic16_emitpcode(POC_BTFSC, 
7986                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7987         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7988       }
7989       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7990       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7991       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7992       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7993     } else {
7994       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7995       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7996       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7997       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7998       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7999       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8000       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8001       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8002       if(sign) {
8003         pic16_emitpcode(POC_BTFSC, 
8004                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8005         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8006       }
8007       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8008       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8009
8010         
8011     }
8012
8013     break;
8014   case 7:
8015     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8016     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8017     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8018     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8019     if(sign) {
8020       emitSKPNC;
8021       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8022     } else 
8023       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8024   }
8025 }
8026
8027
8028 /*-----------------------------------------------------------------*/
8029 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8030 /*-----------------------------------------------------------------*/
8031 static void shiftLLeftOrResult (operand *left, int offl,
8032                                 operand *result, int offr, int shCount)
8033 {
8034     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8035
8036     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8037     /* shift left accumulator */
8038     AccLsh(shCount);
8039     /* or with result */
8040     /* back to result */
8041     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8042 }
8043
8044 /*-----------------------------------------------------------------*/
8045 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8046 /*-----------------------------------------------------------------*/
8047 static void shiftRLeftOrResult (operand *left, int offl,
8048                                 operand *result, int offr, int shCount)
8049 {
8050     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8051     
8052     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8053     /* shift right accumulator */
8054     AccRsh(shCount, 1);
8055     /* or with result */
8056     /* back to result */
8057     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8058 }
8059
8060 /*-----------------------------------------------------------------*/
8061 /* genlshOne - left shift a one byte quantity by known count       */
8062 /*-----------------------------------------------------------------*/
8063 static void genlshOne (operand *result, operand *left, int shCount)
8064 {       
8065     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8066     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8067 }
8068
8069 /*-----------------------------------------------------------------*/
8070 /* genlshTwo - left shift two bytes by known amount != 0           */
8071 /*-----------------------------------------------------------------*/
8072 static void genlshTwo (operand *result,operand *left, int shCount)
8073 {
8074     int size;
8075     
8076     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8077     size = pic16_getDataSize(result);
8078
8079     /* if shCount >= 8 */
8080     if (shCount >= 8) {
8081         shCount -= 8 ;
8082
8083         if (size > 1){
8084             if (shCount)
8085                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8086             else 
8087                 movLeft2Result(left, LSB, result, MSB16);
8088         }
8089         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8090     }
8091
8092     /*  1 <= shCount <= 7 */
8093     else {  
8094         if(size == 1)
8095             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8096         else 
8097             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8098     }
8099 }
8100
8101 /*-----------------------------------------------------------------*/
8102 /* shiftLLong - shift left one long from left to result            */
8103 /* offr = LSB or MSB16                                             */
8104 /*-----------------------------------------------------------------*/
8105 static void shiftLLong (operand *left, operand *result, int offr )
8106 {
8107     int size = AOP_SIZE(result);
8108     int same = pic16_sameRegs(AOP(left),AOP(result));
8109         int i;
8110
8111     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8112
8113         if (same && (offr == MSB16)) { //shift one byte
8114                 for(i=size-1;i>=MSB16;i--) {
8115                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8116                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8117                 }
8118         } else {
8119                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8120         }
8121         
8122     if (size >= LSB+offr ){
8123                 if (same) {
8124                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8125                 } else {
8126                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8127                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8128                 }
8129          }
8130
8131     if(size >= MSB16+offr){
8132                 if (same) {
8133                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8134                 } else {
8135                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8136                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8137                 }
8138     }
8139
8140     if(size >= MSB24+offr){
8141                 if (same) {
8142                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8143                 } else {
8144                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8145                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8146                 }
8147     }
8148
8149     if(size > MSB32+offr){
8150                 if (same) {
8151                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8152                 } else {
8153                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8154                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8155                 }
8156     }
8157     if(offr != LSB)
8158                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8159
8160 }
8161
8162 /*-----------------------------------------------------------------*/
8163 /* genlshFour - shift four byte by a known amount != 0             */
8164 /*-----------------------------------------------------------------*/
8165 static void genlshFour (operand *result, operand *left, int shCount)
8166 {
8167     int size;
8168
8169     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8170     size = AOP_SIZE(result);
8171
8172     /* if shifting more that 3 bytes */
8173     if (shCount >= 24 ) {
8174         shCount -= 24;
8175         if (shCount)
8176             /* lowest order of left goes to the highest
8177             order of the destination */
8178             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8179         else
8180             movLeft2Result(left, LSB, result, MSB32);
8181
8182                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8183                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8184                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8185
8186         return;
8187     }
8188
8189     /* more than two bytes */
8190     else if ( shCount >= 16 ) {
8191         /* lower order two bytes goes to higher order two bytes */
8192         shCount -= 16;
8193         /* if some more remaining */
8194         if (shCount)
8195             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8196         else {
8197             movLeft2Result(left, MSB16, result, MSB32);
8198             movLeft2Result(left, LSB, result, MSB24);
8199         }
8200                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8201                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8202         return;
8203     }    
8204
8205     /* if more than 1 byte */
8206     else if ( shCount >= 8 ) {
8207         /* lower order three bytes goes to higher order  three bytes */
8208         shCount -= 8;
8209         if(size == 2){
8210             if(shCount)
8211                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8212             else
8213                 movLeft2Result(left, LSB, result, MSB16);
8214         }
8215         else{   /* size = 4 */
8216             if(shCount == 0){
8217                 movLeft2Result(left, MSB24, result, MSB32);
8218                 movLeft2Result(left, MSB16, result, MSB24);
8219                 movLeft2Result(left, LSB, result, MSB16);
8220                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8221             }
8222             else if(shCount == 1)
8223                 shiftLLong(left, result, MSB16);
8224             else{
8225                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8226                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8227                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8228                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8229             }
8230         }
8231     }
8232
8233     /* 1 <= shCount <= 7 */
8234     else if(shCount <= 3)
8235     { 
8236         shiftLLong(left, result, LSB);
8237         while(--shCount >= 1)
8238             shiftLLong(result, result, LSB);
8239     }
8240     /* 3 <= shCount <= 7, optimize */
8241     else{
8242         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8243         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8244         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8245     }
8246 }
8247
8248 /*-----------------------------------------------------------------*/
8249 /* genLeftShiftLiteral - left shifting by known count              */
8250 /*-----------------------------------------------------------------*/
8251 static void genLeftShiftLiteral (operand *left,
8252                                  operand *right,
8253                                  operand *result,
8254                                  iCode *ic)
8255 {    
8256     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8257     int size;
8258
8259     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8260     pic16_freeAsmop(right,NULL,ic,TRUE);
8261
8262     pic16_aopOp(left,ic,FALSE);
8263     pic16_aopOp(result,ic,FALSE);
8264
8265     size = getSize(operandType(result));
8266
8267 #if VIEW_SIZE
8268     pic16_emitcode("; shift left ","result %d, left %d",size,
8269              AOP_SIZE(left));
8270 #endif
8271
8272     /* I suppose that the left size >= result size */
8273     if(shCount == 0){
8274         while(size--){
8275             movLeft2Result(left, size, result, size);
8276         }
8277     }
8278
8279     else if(shCount >= (size * 8))
8280         while(size--)
8281             pic16_aopPut(AOP(result),zero,size);
8282     else{
8283         switch (size) {
8284             case 1:
8285                 genlshOne (result,left,shCount);
8286                 break;
8287
8288             case 2:
8289             case 3:
8290                 genlshTwo (result,left,shCount);
8291                 break;
8292
8293             case 4:
8294                 genlshFour (result,left,shCount);
8295                 break;
8296         }
8297     }
8298     pic16_freeAsmop(left,NULL,ic,TRUE);
8299     pic16_freeAsmop(result,NULL,ic,TRUE);
8300 }
8301
8302 /*-----------------------------------------------------------------*
8303  * genMultiAsm - repeat assembly instruction for size of register.
8304  * if endian == 1, then the high byte (i.e base address + size of 
8305  * register) is used first else the low byte is used first;
8306  *-----------------------------------------------------------------*/
8307 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8308 {
8309
8310   int offset = 0;
8311
8312   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8313
8314   if(!reg)
8315     return;
8316
8317   if(!endian) {
8318     endian = 1;
8319   } else {
8320     endian = -1;
8321     offset = size-1;
8322   }
8323
8324   while(size--) {
8325     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8326     offset += endian;
8327   }
8328
8329 }
8330 /*-----------------------------------------------------------------*/
8331 /* genLeftShift - generates code for left shifting                 */
8332 /*-----------------------------------------------------------------*/
8333 static void genLeftShift (iCode *ic)
8334 {
8335   operand *left,*right, *result;
8336   int size, offset;
8337   char *l;
8338   symbol *tlbl , *tlbl1;
8339   pCodeOp *pctemp;
8340
8341   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8342
8343   right = IC_RIGHT(ic);
8344   left  = IC_LEFT(ic);
8345   result = IC_RESULT(ic);
8346
8347   pic16_aopOp(right,ic,FALSE);
8348
8349   /* if the shift count is known then do it 
8350      as efficiently as possible */
8351   if (AOP_TYPE(right) == AOP_LIT) {
8352     genLeftShiftLiteral (left,right,result,ic);
8353     return ;
8354   }
8355
8356   /* shift count is unknown then we have to form 
8357      a loop get the loop count in B : Note: we take
8358      only the lower order byte since shifting
8359      more that 32 bits make no sense anyway, ( the
8360      largest size of an object can be only 32 bits ) */  
8361
8362     
8363   pic16_aopOp(left,ic,FALSE);
8364   pic16_aopOp(result,ic,FALSE);
8365
8366   /* now move the left to the result if they are not the
8367      same */
8368   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8369       AOP_SIZE(result) > 1) {
8370
8371     size = AOP_SIZE(result);
8372     offset=0;
8373     while (size--) {
8374       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8375       if (*l == '@' && (IS_AOP_PREG(result))) {
8376
8377         pic16_emitcode("mov","a,%s",l);
8378         pic16_aopPut(AOP(result),"a",offset);
8379       } else {
8380         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8381         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8382         //pic16_aopPut(AOP(result),l,offset);
8383       }
8384       offset++;
8385     }
8386   }
8387
8388   size = AOP_SIZE(result);
8389
8390   /* if it is only one byte then */
8391   if (size == 1) {
8392     if(optimized_for_speed) {
8393       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8394       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8395       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8396       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8397       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8398       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8399       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8400       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8401       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8402       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8403       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8404       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8405     } else {
8406
8407       tlbl = newiTempLabel(NULL);
8408       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8409                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8410                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8411       }
8412
8413       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8414       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8415       pic16_emitpLabel(tlbl->key);
8416       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8417       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8418       emitSKPC;
8419       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8420     }
8421     goto release ;
8422   }
8423     
8424   if (pic16_sameRegs(AOP(left),AOP(result))) {
8425
8426     tlbl = newiTempLabel(NULL);
8427     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8428     genMultiAsm(POC_RRCF, result, size,1);
8429     pic16_emitpLabel(tlbl->key);
8430     genMultiAsm(POC_RLCF, result, size,0);
8431     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8432     emitSKPC;
8433     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8434     goto release;
8435   }
8436
8437   //tlbl = newiTempLabel(NULL);
8438   //offset = 0 ;   
8439   //tlbl1 = newiTempLabel(NULL);
8440
8441   //reAdjustPreg(AOP(result));    
8442     
8443   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8444   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8445   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8446   //MOVA(l);
8447   //pic16_emitcode("add","a,acc");         
8448   //pic16_aopPut(AOP(result),"a",offset++);
8449   //while (--size) {
8450   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8451   //  MOVA(l);
8452   //  pic16_emitcode("rlc","a");         
8453   //  pic16_aopPut(AOP(result),"a",offset++);
8454   //}
8455   //reAdjustPreg(AOP(result));
8456
8457   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8458   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8459
8460
8461   tlbl = newiTempLabel(NULL);
8462   tlbl1= newiTempLabel(NULL);
8463
8464   size = AOP_SIZE(result);
8465   offset = 1;
8466
8467   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8468
8469   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8470
8471   /* offset should be 0, 1 or 3 */
8472   
8473   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8474   emitSKPNZ;
8475   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8476
8477   pic16_emitpcode(POC_MOVWF, pctemp);
8478
8479
8480   pic16_emitpLabel(tlbl->key);
8481
8482   emitCLRC;
8483   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8484   while(--size)
8485     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8486
8487   pic16_emitpcode(POC_DECFSZ,  pctemp);
8488   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8489   pic16_emitpLabel(tlbl1->key);
8490
8491   pic16_popReleaseTempReg(pctemp);
8492
8493
8494  release:
8495   pic16_freeAsmop (right,NULL,ic,TRUE);
8496   pic16_freeAsmop(left,NULL,ic,TRUE);
8497   pic16_freeAsmop(result,NULL,ic,TRUE);
8498 }
8499
8500 /*-----------------------------------------------------------------*/
8501 /* genrshOne - right shift a one byte quantity by known count      */
8502 /*-----------------------------------------------------------------*/
8503 static void genrshOne (operand *result, operand *left,
8504                        int shCount, int sign)
8505 {
8506     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8507     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8508 }
8509
8510 /*-----------------------------------------------------------------*/
8511 /* genrshTwo - right shift two bytes by known amount != 0          */
8512 /*-----------------------------------------------------------------*/
8513 static void genrshTwo (operand *result,operand *left,
8514                        int shCount, int sign)
8515 {
8516   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8517   /* if shCount >= 8 */
8518   if (shCount >= 8) {
8519     shCount -= 8 ;
8520     if (shCount)
8521       shiftR1Left2Result(left, MSB16, result, LSB,
8522                          shCount, sign);
8523     else
8524       movLeft2Result(left, MSB16, result, LSB);
8525
8526     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8527
8528     if(sign) {
8529       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8530       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8531     }
8532   }
8533
8534   /*  1 <= shCount <= 7 */
8535   else
8536     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8537 }
8538
8539 /*-----------------------------------------------------------------*/
8540 /* shiftRLong - shift right one long from left to result           */
8541 /* offl = LSB or MSB16                                             */
8542 /*-----------------------------------------------------------------*/
8543 static void shiftRLong (operand *left, int offl,
8544                         operand *result, int sign)
8545 {
8546     int size = AOP_SIZE(result);
8547     int same = pic16_sameRegs(AOP(left),AOP(result));
8548     int i;
8549     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8550
8551         if (same && (offl == MSB16)) { //shift one byte right
8552                 for(i=MSB16;i<size;i++) {
8553                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8554                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8555                 }
8556         }
8557
8558     if(sign)
8559                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8560         else
8561                 emitCLRC;
8562
8563         if (same) {
8564                 if (offl == LSB)
8565                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8566         } else {
8567         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8568         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8569         }
8570
8571     if(offl == MSB16) {
8572         /* add sign of "a" */
8573         pic16_addSign(result, MSB32, sign);
8574         }
8575
8576         if (same) {
8577         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8578         } else {
8579         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8580         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8581         }
8582         
8583         if (same) {
8584         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8585         } else {
8586         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8587         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8588         }
8589
8590         if (same) {
8591         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8592         } else {
8593         if(offl == LSB){
8594                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8595                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8596         }
8597         }
8598 }
8599
8600 /*-----------------------------------------------------------------*/
8601 /* genrshFour - shift four byte by a known amount != 0             */
8602 /*-----------------------------------------------------------------*/
8603 static void genrshFour (operand *result, operand *left,
8604                         int shCount, int sign)
8605 {
8606   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8607   /* if shifting more that 3 bytes */
8608   if(shCount >= 24 ) {
8609     shCount -= 24;
8610     if(shCount)
8611       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8612     else
8613       movLeft2Result(left, MSB32, result, LSB);
8614
8615     pic16_addSign(result, MSB16, sign);
8616   }
8617   else if(shCount >= 16){
8618     shCount -= 16;
8619     if(shCount)
8620       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8621     else{
8622       movLeft2Result(left, MSB24, result, LSB);
8623       movLeft2Result(left, MSB32, result, MSB16);
8624     }
8625     pic16_addSign(result, MSB24, sign);
8626   }
8627   else if(shCount >= 8){
8628     shCount -= 8;
8629     if(shCount == 1)
8630       shiftRLong(left, MSB16, result, sign);
8631     else if(shCount == 0){
8632       movLeft2Result(left, MSB16, result, LSB);
8633       movLeft2Result(left, MSB24, result, MSB16);
8634       movLeft2Result(left, MSB32, result, MSB24);
8635       pic16_addSign(result, MSB32, sign);
8636     }
8637     else{ //shcount >= 2
8638       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8639       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8640       /* the last shift is signed */
8641       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8642       pic16_addSign(result, MSB32, sign);
8643     }
8644   }
8645   else{   /* 1 <= shCount <= 7 */
8646     if(shCount <= 2){
8647       shiftRLong(left, LSB, result, sign);
8648       if(shCount == 2)
8649         shiftRLong(result, LSB, result, sign);
8650     }
8651     else{
8652       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8653       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8654       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8655     }
8656   }
8657 }
8658
8659 /*-----------------------------------------------------------------*/
8660 /* genRightShiftLiteral - right shifting by known count            */
8661 /*-----------------------------------------------------------------*/
8662 static void genRightShiftLiteral (operand *left,
8663                                   operand *right,
8664                                   operand *result,
8665                                   iCode *ic,
8666                                   int sign)
8667 {    
8668   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8669   int lsize,res_size;
8670
8671   pic16_freeAsmop(right,NULL,ic,TRUE);
8672
8673   pic16_aopOp(left,ic,FALSE);
8674   pic16_aopOp(result,ic,FALSE);
8675
8676   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8677
8678 #if VIEW_SIZE
8679   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8680                  AOP_SIZE(left));
8681 #endif
8682
8683   lsize = pic16_getDataSize(left);
8684   res_size = pic16_getDataSize(result);
8685   /* test the LEFT size !!! */
8686
8687   /* I suppose that the left size >= result size */
8688   if(shCount == 0){
8689     while(res_size--)
8690       movLeft2Result(left, lsize, result, res_size);
8691   }
8692
8693   else if(shCount >= (lsize * 8)){
8694
8695     if(res_size == 1) {
8696       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8697       if(sign) {
8698         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8699         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8700       }
8701     } else {
8702
8703       if(sign) {
8704         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8705         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8706         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8707         while(res_size--)
8708           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8709
8710       } else {
8711
8712         while(res_size--)
8713           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8714       }
8715     }
8716   } else {
8717
8718     switch (res_size) {
8719     case 1:
8720       genrshOne (result,left,shCount,sign);
8721       break;
8722
8723     case 2:
8724       genrshTwo (result,left,shCount,sign);
8725       break;
8726
8727     case 4:
8728       genrshFour (result,left,shCount,sign);
8729       break;
8730     default :
8731       break;
8732     }
8733
8734   }
8735
8736   pic16_freeAsmop(left,NULL,ic,TRUE);
8737   pic16_freeAsmop(result,NULL,ic,TRUE);
8738 }
8739
8740 /*-----------------------------------------------------------------*/
8741 /* genSignedRightShift - right shift of signed number              */
8742 /*-----------------------------------------------------------------*/
8743 static void genSignedRightShift (iCode *ic)
8744 {
8745   operand *right, *left, *result;
8746   int size, offset;
8747   //  char *l;
8748   symbol *tlbl, *tlbl1 ;
8749   pCodeOp *pctemp;
8750
8751   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8752
8753   /* we do it the hard way put the shift count in b
8754      and loop thru preserving the sign */
8755   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8756
8757   right = IC_RIGHT(ic);
8758   left  = IC_LEFT(ic);
8759   result = IC_RESULT(ic);
8760
8761   pic16_aopOp(right,ic,FALSE);  
8762   pic16_aopOp(left,ic,FALSE);
8763   pic16_aopOp(result,ic,FALSE);
8764
8765
8766   if ( AOP_TYPE(right) == AOP_LIT) {
8767     genRightShiftLiteral (left,right,result,ic,1);
8768     return ;
8769   }
8770   /* shift count is unknown then we have to form 
8771      a loop get the loop count in B : Note: we take
8772      only the lower order byte since shifting
8773      more that 32 bits make no sense anyway, ( the
8774      largest size of an object can be only 32 bits ) */  
8775
8776   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8777   //pic16_emitcode("inc","b");
8778   //pic16_freeAsmop (right,NULL,ic,TRUE);
8779   //pic16_aopOp(left,ic,FALSE);
8780   //pic16_aopOp(result,ic,FALSE);
8781
8782   /* now move the left to the result if they are not the
8783      same */
8784   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8785       AOP_SIZE(result) > 1) {
8786
8787     size = AOP_SIZE(result);
8788     offset=0;
8789     while (size--) { 
8790       /*
8791         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8792         if (*l == '@' && IS_AOP_PREG(result)) {
8793
8794         pic16_emitcode("mov","a,%s",l);
8795         pic16_aopPut(AOP(result),"a",offset);
8796         } else
8797         pic16_aopPut(AOP(result),l,offset);
8798       */
8799       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8800       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8801
8802       offset++;
8803     }
8804   }
8805
8806   /* mov the highest order bit to OVR */    
8807   tlbl = newiTempLabel(NULL);
8808   tlbl1= newiTempLabel(NULL);
8809
8810   size = AOP_SIZE(result);
8811   offset = size - 1;
8812
8813   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8814
8815   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8816
8817   /* offset should be 0, 1 or 3 */
8818   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8819   emitSKPNZ;
8820   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8821
8822   pic16_emitpcode(POC_MOVWF, pctemp);
8823
8824
8825   pic16_emitpLabel(tlbl->key);
8826
8827   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8828   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8829
8830   while(--size) {
8831     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8832   }
8833
8834   pic16_emitpcode(POC_DECFSZ,  pctemp);
8835   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8836   pic16_emitpLabel(tlbl1->key);
8837
8838   pic16_popReleaseTempReg(pctemp);
8839 #if 0
8840   size = AOP_SIZE(result);
8841   offset = size - 1;
8842   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8843   pic16_emitcode("rlc","a");
8844   pic16_emitcode("mov","ov,c");
8845   /* if it is only one byte then */
8846   if (size == 1) {
8847     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8848     MOVA(l);
8849     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8850     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8851     pic16_emitcode("mov","c,ov");
8852     pic16_emitcode("rrc","a");
8853     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8854     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8855     pic16_aopPut(AOP(result),"a",0);
8856     goto release ;
8857   }
8858
8859   reAdjustPreg(AOP(result));
8860   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8861   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8862   pic16_emitcode("mov","c,ov");
8863   while (size--) {
8864     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8865     MOVA(l);
8866     pic16_emitcode("rrc","a");         
8867     pic16_aopPut(AOP(result),"a",offset--);
8868   }
8869   reAdjustPreg(AOP(result));
8870   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8871   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8872
8873  release:
8874 #endif
8875
8876   pic16_freeAsmop(left,NULL,ic,TRUE);
8877   pic16_freeAsmop(result,NULL,ic,TRUE);
8878   pic16_freeAsmop(right,NULL,ic,TRUE);
8879 }
8880
8881 /*-----------------------------------------------------------------*/
8882 /* genRightShift - generate code for right shifting                */
8883 /*-----------------------------------------------------------------*/
8884 static void genRightShift (iCode *ic)
8885 {
8886     operand *right, *left, *result;
8887     sym_link *letype ;
8888     int size, offset;
8889     char *l;
8890     symbol *tlbl, *tlbl1 ;
8891
8892     /* if signed then we do it the hard way preserve the
8893     sign bit moving it inwards */
8894     letype = getSpec(operandType(IC_LEFT(ic)));
8895     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8896
8897     if (!SPEC_USIGN(letype)) {
8898         genSignedRightShift (ic);
8899         return ;
8900     }
8901
8902     /* signed & unsigned types are treated the same : i.e. the
8903     signed is NOT propagated inwards : quoting from the
8904     ANSI - standard : "for E1 >> E2, is equivalent to division
8905     by 2**E2 if unsigned or if it has a non-negative value,
8906     otherwise the result is implementation defined ", MY definition
8907     is that the sign does not get propagated */
8908
8909     right = IC_RIGHT(ic);
8910     left  = IC_LEFT(ic);
8911     result = IC_RESULT(ic);
8912
8913     pic16_aopOp(right,ic,FALSE);
8914
8915     /* if the shift count is known then do it 
8916     as efficiently as possible */
8917     if (AOP_TYPE(right) == AOP_LIT) {
8918         genRightShiftLiteral (left,right,result,ic, 0);
8919         return ;
8920     }
8921
8922     /* shift count is unknown then we have to form 
8923     a loop get the loop count in B : Note: we take
8924     only the lower order byte since shifting
8925     more that 32 bits make no sense anyway, ( the
8926     largest size of an object can be only 32 bits ) */  
8927
8928     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8929     pic16_emitcode("inc","b");
8930     pic16_aopOp(left,ic,FALSE);
8931     pic16_aopOp(result,ic,FALSE);
8932
8933     /* now move the left to the result if they are not the
8934     same */
8935     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8936         AOP_SIZE(result) > 1) {
8937
8938         size = AOP_SIZE(result);
8939         offset=0;
8940         while (size--) {
8941             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8942             if (*l == '@' && IS_AOP_PREG(result)) {
8943
8944                 pic16_emitcode("mov","a,%s",l);
8945                 pic16_aopPut(AOP(result),"a",offset);
8946             } else
8947                 pic16_aopPut(AOP(result),l,offset);
8948             offset++;
8949         }
8950     }
8951
8952     tlbl = newiTempLabel(NULL);
8953     tlbl1= newiTempLabel(NULL);
8954     size = AOP_SIZE(result);
8955     offset = size - 1;
8956
8957     /* if it is only one byte then */
8958     if (size == 1) {
8959
8960       tlbl = newiTempLabel(NULL);
8961       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8962         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8963         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8964       }
8965
8966       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8967       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8968       pic16_emitpLabel(tlbl->key);
8969       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8970       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8971       emitSKPC;
8972       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8973
8974       goto release ;
8975     }
8976
8977     reAdjustPreg(AOP(result));
8978     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8979     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8980     CLRC;
8981     while (size--) {
8982         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8983         MOVA(l);
8984         pic16_emitcode("rrc","a");         
8985         pic16_aopPut(AOP(result),"a",offset--);
8986     }
8987     reAdjustPreg(AOP(result));
8988
8989     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8990     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8991
8992 release:
8993     pic16_freeAsmop(left,NULL,ic,TRUE);
8994     pic16_freeAsmop (right,NULL,ic,TRUE);
8995     pic16_freeAsmop(result,NULL,ic,TRUE);
8996 }
8997
8998 /*-----------------------------------------------------------------*/
8999 /* genUnpackBits - generates code for unpacking bits               */
9000 /*-----------------------------------------------------------------*/
9001 static void genUnpackBits (operand *result, char *rname, int ptype)
9002 {    
9003     int shCnt ;
9004     int rlen = 0 ;
9005     sym_link *etype;
9006     int offset = 0 ;
9007
9008         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9009         etype = getSpec(operandType(result));
9010
9011         /* read the first byte  */
9012         switch (ptype) {
9013                 case POINTER:
9014                 case IPOINTER:
9015                 case PPOINTER:
9016                 case FPOINTER:
9017                 case GPOINTER:
9018                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9019                         break;
9020                 case CPOINTER:
9021                         pic16_emitcode("clr","a");
9022                         pic16_emitcode("movc","a","@a+dptr");
9023                         break;
9024         }
9025         
9026
9027         /* if we have bitdisplacement then it fits   */
9028         /* into this byte completely or if length is */
9029         /* less than a byte                          */
9030         if ((shCnt = SPEC_BSTR(etype)) || 
9031                 (SPEC_BLEN(etype) <= 8))  {
9032
9033                 /* shift right acc */
9034                 AccRsh(shCnt, 0);
9035
9036                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9037                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9038
9039 /* VR -- normally I would use the following, but since we use the hack,
9040  * to avoid the masking from AccRsh, why not mask it right now? */
9041
9042 /*
9043                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9044 */
9045
9046                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9047           return ;
9048         }
9049
9050
9051
9052         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9053         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9054         exit(-1);
9055
9056     /* bit field did not fit in a byte  */
9057     rlen = SPEC_BLEN(etype) - 8;
9058     pic16_aopPut(AOP(result),"a",offset++);
9059
9060     while (1)  {
9061
9062         switch (ptype) {
9063         case POINTER:
9064         case IPOINTER:
9065             pic16_emitcode("inc","%s",rname);
9066             pic16_emitcode("mov","a,@%s",rname);
9067             break;
9068             
9069         case PPOINTER:
9070             pic16_emitcode("inc","%s",rname);
9071             pic16_emitcode("movx","a,@%s",rname);
9072             break;
9073
9074         case FPOINTER:
9075             pic16_emitcode("inc","dptr");
9076             pic16_emitcode("movx","a,@dptr");
9077             break;
9078             
9079         case CPOINTER:
9080             pic16_emitcode("clr","a");
9081             pic16_emitcode("inc","dptr");
9082             pic16_emitcode("movc","a","@a+dptr");
9083             break;
9084             
9085         case GPOINTER:
9086             pic16_emitcode("inc","dptr");
9087             pic16_emitcode("lcall","__gptrget");
9088             break;
9089         }
9090
9091         rlen -= 8;            
9092         /* if we are done */
9093         if ( rlen <= 0 )
9094             break ;
9095         
9096         pic16_aopPut(AOP(result),"a",offset++);
9097                               
9098     }
9099     
9100     if (rlen) {
9101         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9102         pic16_aopPut(AOP(result),"a",offset);          
9103     }
9104     
9105     return ;
9106 }
9107
9108
9109 static void genDataPointerGet(operand *left,
9110                               operand *result,
9111                               iCode *ic)
9112 {
9113   int size, offset = 0, leoffset=0 ;
9114
9115         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9116         pic16_aopOp(result, ic, FALSE);
9117
9118         size = AOP_SIZE(result);
9119 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9120
9121
9122 #if 0
9123         /* The following tests may save a redudant movff instruction when
9124          * accessing unions */
9125          
9126         /* if they are the same */
9127         if (operandsEqu (left, result)) {
9128                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9129                 goto release;
9130         }
9131 #endif
9132
9133 #if 0
9134         /* if they are the same registers */
9135         if (pic16_sameRegs(AOP(left),AOP(result))) {
9136                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9137                 goto release;
9138         }
9139 #endif
9140
9141 #if 1
9142         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9143                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9144                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9145                 goto release;
9146         }
9147 #endif
9148
9149
9150 #if 0
9151         if ( AOP_TYPE(left) == AOP_PCODE) {
9152                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9153                                 AOP(left)->aopu.pcop->name,
9154                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9155                                 PCOR(AOP(left)->aopu.pcop)->instance:
9156                                 PCOI(AOP(left)->aopu.pcop)->offset);
9157         }
9158 #endif
9159
9160         if(AOP(left)->aopu.pcop->type == PO_DIR)
9161                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9162
9163         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9164
9165         while (size--) {
9166                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9167                 
9168                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9169                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9170                         mov2w(AOP(left), offset); // patch 8
9171                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9172                 } else {
9173                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9174                                 pic16_popGet(AOP(left), offset), //patch 8
9175                                 pic16_popGet(AOP(result), offset)));
9176                 }
9177
9178                 offset++;
9179                 leoffset++;
9180         }
9181
9182 release:
9183     pic16_freeAsmop(result,NULL,ic,TRUE);
9184 }
9185
9186 void pic16_loadFSR0(operand *op)
9187 {
9188         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9189 }
9190
9191
9192 /*-----------------------------------------------------------------*/
9193 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9194 /*-----------------------------------------------------------------*/
9195 static void genNearPointerGet (operand *left, 
9196                                operand *result, 
9197                                iCode *ic)
9198 {
9199     asmop *aop = NULL;
9200     //regs *preg = NULL ;
9201     sym_link *rtype, *retype;
9202     sym_link *ltype = operandType(left);    
9203
9204         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9205         rtype = operandType(result);
9206         retype= getSpec(rtype);
9207     
9208         pic16_aopOp(left,ic,FALSE);
9209
9210 //      pic16_DumpOp("(left)",left);
9211 //      pic16_DumpOp("(result)",result);
9212
9213         /* if left is rematerialisable and
9214          * result is not bit variable type and
9215          * the left is pointer to data space i.e
9216          * lower 128 bytes of space */
9217         if (AOP_TYPE(left) == AOP_PCODE
9218                 && !IS_BITFIELD(retype)
9219                 && DCL_TYPE(ltype) == POINTER) {
9220
9221                 genDataPointerGet (left,result,ic);
9222                 pic16_freeAsmop(left, NULL, ic, TRUE);
9223           return ;
9224         }
9225     
9226         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9227
9228         /* if the value is already in a pointer register
9229          * then don't need anything more */
9230         if (!AOP_INPREG(AOP(left))) {
9231                 /* otherwise get a free pointer register */
9232                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9233                 
9234                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9235                 if( (AOP_TYPE(left) == AOP_PCODE) 
9236                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9237                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9238                 {
9239                         pic16_loadFSR0( left );  // patch 10
9240                 } else {
9241                         // set up FSR0 with address from left
9242                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9243                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9244                 }
9245         }
9246 //       else
9247 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9248     
9249         pic16_aopOp (result,ic,FALSE);
9250     
9251       /* if bitfield then unpack the bits */
9252     if (IS_BITFIELD(retype)) 
9253         genUnpackBits (result, NULL, POINTER);
9254     else {
9255         /* we have can just get the values */
9256       int size = AOP_SIZE(result);
9257       int offset = 0;   
9258         
9259       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9260
9261
9262         /* fsr0 is loaded already -- VR */
9263 //      pic16_loadFSR0( left );
9264
9265 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9266 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9267       while(size--) {
9268
9269         if(size) {
9270                 pic16_emitpcode(POC_MOVFF,
9271                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9272                                 pic16_popGet(AOP(result), offset++)));
9273         } else {
9274                 pic16_emitpcode(POC_MOVFF,
9275                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9276                                 pic16_popGet(AOP(result), offset++)));
9277         }
9278       }
9279 #if 0
9280 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9281 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9282         if(size)
9283           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9284 #endif
9285 /*
9286         while (size--) {
9287             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9288
9289                 pic16_emitcode("mov","a,@%s",rname);
9290                 pic16_aopPut(AOP(result),"a",offset);
9291             } else {
9292                 sprintf(buffer,"@%s",rname);
9293                 pic16_aopPut(AOP(result),buffer,offset);
9294             }
9295             offset++ ;
9296             if (size)
9297                 pic16_emitcode("inc","%s",rname);
9298         }
9299 */
9300     }
9301
9302     /* now some housekeeping stuff */
9303     if (aop) {
9304         /* we had to allocate for this iCode */
9305     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9306         pic16_freeAsmop(NULL,aop,ic,TRUE);
9307     } else { 
9308         /* we did not allocate which means left
9309            already in a pointer register, then
9310            if size > 0 && this could be used again
9311            we have to point it back to where it 
9312            belongs */
9313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9314         if (AOP_SIZE(result) > 1 &&
9315             !OP_SYMBOL(left)->remat &&
9316             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9317               ic->depth )) {
9318 //          int size = AOP_SIZE(result) - 1;
9319 //          while (size--)
9320 //              pic16_emitcode("dec","%s",rname);
9321         }
9322     }
9323
9324     /* done */
9325     pic16_freeAsmop(left,NULL,ic,TRUE);
9326     pic16_freeAsmop(result,NULL,ic,TRUE);
9327      
9328 }
9329
9330 /*-----------------------------------------------------------------*/
9331 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9332 /*-----------------------------------------------------------------*/
9333 static void genPagedPointerGet (operand *left, 
9334                                operand *result, 
9335                                iCode *ic)
9336 {
9337     asmop *aop = NULL;
9338     regs *preg = NULL ;
9339     char *rname ;
9340     sym_link *rtype, *retype;    
9341
9342     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9343
9344     rtype = operandType(result);
9345     retype= getSpec(rtype);
9346     
9347     pic16_aopOp(left,ic,FALSE);
9348
9349   /* if the value is already in a pointer register
9350        then don't need anything more */
9351     if (!AOP_INPREG(AOP(left))) {
9352         /* otherwise get a free pointer register */
9353         aop = newAsmop(0);
9354         preg = getFreePtr(ic,&aop,FALSE);
9355         pic16_emitcode("mov","%s,%s",
9356                 preg->name,
9357                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9358         rname = preg->name ;
9359     } else
9360         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9361     
9362     pic16_freeAsmop(left,NULL,ic,TRUE);
9363     pic16_aopOp (result,ic,FALSE);
9364
9365     /* if bitfield then unpack the bits */
9366     if (IS_BITFIELD(retype)) 
9367         genUnpackBits (result,rname,PPOINTER);
9368     else {
9369         /* we have can just get the values */
9370         int size = AOP_SIZE(result);
9371         int offset = 0 ;        
9372         
9373         while (size--) {
9374             
9375             pic16_emitcode("movx","a,@%s",rname);
9376             pic16_aopPut(AOP(result),"a",offset);
9377             
9378             offset++ ;
9379             
9380             if (size)
9381                 pic16_emitcode("inc","%s",rname);
9382         }
9383     }
9384
9385     /* now some housekeeping stuff */
9386     if (aop) {
9387         /* we had to allocate for this iCode */
9388         pic16_freeAsmop(NULL,aop,ic,TRUE);
9389     } else { 
9390         /* we did not allocate which means left
9391            already in a pointer register, then
9392            if size > 0 && this could be used again
9393            we have to point it back to where it 
9394            belongs */
9395         if (AOP_SIZE(result) > 1 &&
9396             !OP_SYMBOL(left)->remat &&
9397             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9398               ic->depth )) {
9399             int size = AOP_SIZE(result) - 1;
9400             while (size--)
9401                 pic16_emitcode("dec","%s",rname);
9402         }
9403     }
9404
9405     /* done */
9406     pic16_freeAsmop(result,NULL,ic,TRUE);
9407     
9408         
9409 }
9410
9411 /*-----------------------------------------------------------------*/
9412 /* genFarPointerGet - gget value from far space                    */
9413 /*-----------------------------------------------------------------*/
9414 static void genFarPointerGet (operand *left,
9415                               operand *result, iCode *ic)
9416 {
9417     int size, offset ;
9418     sym_link *retype = getSpec(operandType(result));
9419
9420     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9421
9422     pic16_aopOp(left,ic,FALSE);
9423
9424     /* if the operand is already in dptr 
9425     then we do nothing else we move the value to dptr */
9426     if (AOP_TYPE(left) != AOP_STR) {
9427         /* if this is remateriazable */
9428         if (AOP_TYPE(left) == AOP_IMMD)
9429             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9430         else { /* we need to get it byte by byte */
9431             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9432             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9433             if (options.model == MODEL_FLAT24)
9434             {
9435                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9436             }
9437         }
9438     }
9439     /* so dptr know contains the address */
9440     pic16_freeAsmop(left,NULL,ic,TRUE);
9441     pic16_aopOp(result,ic,FALSE);
9442
9443     /* if bit then unpack */
9444     if (IS_BITFIELD(retype)) 
9445         genUnpackBits(result,"dptr",FPOINTER);
9446     else {
9447         size = AOP_SIZE(result);
9448         offset = 0 ;
9449
9450         while (size--) {
9451             pic16_emitcode("movx","a,@dptr");
9452             pic16_aopPut(AOP(result),"a",offset++);
9453             if (size)
9454                 pic16_emitcode("inc","dptr");
9455         }
9456     }
9457
9458     pic16_freeAsmop(result,NULL,ic,TRUE);
9459 }
9460 #if 0
9461 /*-----------------------------------------------------------------*/
9462 /* genCodePointerGet - get value from code space                  */
9463 /*-----------------------------------------------------------------*/
9464 static void genCodePointerGet (operand *left,
9465                                 operand *result, iCode *ic)
9466 {
9467     int size, offset ;
9468     sym_link *retype = getSpec(operandType(result));
9469
9470     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9471
9472     pic16_aopOp(left,ic,FALSE);
9473
9474     /* if the operand is already in dptr 
9475     then we do nothing else we move the value to dptr */
9476     if (AOP_TYPE(left) != AOP_STR) {
9477         /* if this is remateriazable */
9478         if (AOP_TYPE(left) == AOP_IMMD)
9479             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9480         else { /* we need to get it byte by byte */
9481             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9482             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9483             if (options.model == MODEL_FLAT24)
9484             {
9485                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9486             }
9487         }
9488     }
9489     /* so dptr know contains the address */
9490     pic16_freeAsmop(left,NULL,ic,TRUE);
9491     pic16_aopOp(result,ic,FALSE);
9492
9493     /* if bit then unpack */
9494     if (IS_BITFIELD(retype)) 
9495         genUnpackBits(result,"dptr",CPOINTER);
9496     else {
9497         size = AOP_SIZE(result);
9498         offset = 0 ;
9499
9500         while (size--) {
9501             pic16_emitcode("clr","a");
9502             pic16_emitcode("movc","a,@a+dptr");
9503             pic16_aopPut(AOP(result),"a",offset++);
9504             if (size)
9505                 pic16_emitcode("inc","dptr");
9506         }
9507     }
9508
9509     pic16_freeAsmop(result,NULL,ic,TRUE);
9510 }
9511 #endif
9512 /*-----------------------------------------------------------------*/
9513 /* genGenPointerGet - gget value from generic pointer space        */
9514 /*-----------------------------------------------------------------*/
9515 static void genGenPointerGet (operand *left,
9516                               operand *result, iCode *ic)
9517 {
9518   int size, offset, lit;
9519   sym_link *retype = getSpec(operandType(result));
9520
9521         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9522         pic16_aopOp(left,ic,FALSE);
9523         pic16_aopOp(result,ic,FALSE);
9524         size = AOP_SIZE(result);
9525
9526         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9527
9528         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9529
9530                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9531                 // load FSR0 from immediate
9532                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9533
9534 //              pic16_loadFSR0( left );
9535
9536                 offset = 0;
9537                 while(size--) {
9538                         if(size) {
9539                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9540                         } else {
9541                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9542                         }
9543                         offset++;
9544                 }
9545                 goto release;
9546
9547         }
9548         else { /* we need to get it byte by byte */
9549                 // set up FSR0 with address from left
9550                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9551                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9552
9553                 offset = 0 ;
9554
9555                 while(size--) {
9556                         if(size) {
9557                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9558                         } else {
9559                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9560                         }
9561                         offset++;
9562                 }
9563                 goto release;
9564         }
9565
9566   /* if bit then unpack */
9567         if (IS_BITFIELD(retype)) 
9568                 genUnpackBits(result,"BAD",GPOINTER);
9569
9570         release:
9571         pic16_freeAsmop(left,NULL,ic,TRUE);
9572         pic16_freeAsmop(result,NULL,ic,TRUE);
9573
9574 }
9575
9576 /*-----------------------------------------------------------------*/
9577 /* genConstPointerGet - get value from const generic pointer space */
9578 /*-----------------------------------------------------------------*/
9579 static void genConstPointerGet (operand *left,
9580                                 operand *result, iCode *ic)
9581 {
9582   //sym_link *retype = getSpec(operandType(result));
9583   // symbol *albl = newiTempLabel(NULL);        // patch 15
9584   // symbol *blbl = newiTempLabel(NULL);        //
9585   // PIC_OPCODE poc;                            // patch 15
9586   int size;
9587   int offset = 0;
9588
9589   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9590   pic16_aopOp(left,ic,FALSE);
9591   pic16_aopOp(result,ic,TRUE);
9592   size = AOP_SIZE(result);
9593
9594   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9595
9596   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9597 #if 0                                                                   // patch 15
9598   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9599   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9600   pic16_emitpLabel(albl->key);
9601
9602   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9603     
9604   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9605   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9606   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9607   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9608   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9609
9610   pic16_emitpLabel(blbl->key);
9611
9612   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9613 #endif                                                                  // patch 15
9614
9615
9616   // set up table pointer
9617   if( (AOP_TYPE(left) == AOP_PCODE) 
9618       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9619           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9620     {
9621       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9622       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9623       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9624       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9625       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9626       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9627     }
9628   else
9629     {
9630       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9631       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9632       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9633     }
9634
9635
9636   while(size--)
9637     {
9638       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9639       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9640       offset++;
9641     }
9642                                                                         // .... patch 15
9643   pic16_freeAsmop(left,NULL,ic,TRUE);
9644   pic16_freeAsmop(result,NULL,ic,TRUE);
9645
9646 }
9647 /*-----------------------------------------------------------------*/
9648 /* genPointerGet - generate code for pointer get                   */
9649 /*-----------------------------------------------------------------*/
9650 static void genPointerGet (iCode *ic)
9651 {
9652     operand *left, *result ;
9653     sym_link *type, *etype;
9654     int p_type;
9655
9656     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9657
9658     left = IC_LEFT(ic);
9659     result = IC_RESULT(ic) ;
9660
9661     /* depending on the type of pointer we need to
9662     move it to the correct pointer register */
9663     type = operandType(left);
9664     etype = getSpec(type);
9665
9666 #if 0
9667     if (IS_PTR_CONST(type))
9668 #else
9669     if (IS_CODEPTR(type))
9670 #endif
9671       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9672
9673     /* if left is of type of pointer then it is simple */
9674     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9675         p_type = DCL_TYPE(type);
9676     else {
9677         /* we have to go by the storage class */
9678         p_type = PTR_TYPE(SPEC_OCLS(etype));
9679
9680         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9681
9682         if (SPEC_OCLS(etype)->codesp ) {
9683           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9684           //p_type = CPOINTER ; 
9685         }
9686         else
9687             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9688               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9689                /*p_type = FPOINTER ;*/ 
9690             else
9691                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9692                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9693 /*                  p_type = PPOINTER; */
9694                 else
9695                     if (SPEC_OCLS(etype) == idata )
9696                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9697 /*                      p_type = IPOINTER; */
9698                     else
9699                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9700 /*                      p_type = POINTER ; */
9701     }
9702
9703     /* now that we have the pointer type we assign
9704     the pointer values */
9705     switch (p_type) {
9706
9707     case POINTER:       
9708     case IPOINTER:
9709         genNearPointerGet (left,result,ic);
9710         break;
9711
9712     case PPOINTER:
9713         genPagedPointerGet(left,result,ic);
9714         break;
9715
9716     case FPOINTER:
9717         genFarPointerGet (left,result,ic);
9718         break;
9719
9720     case CPOINTER:
9721         genConstPointerGet (left,result,ic);
9722         //pic16_emitcodePointerGet (left,result,ic);
9723         break;
9724
9725     case GPOINTER:
9726 #if 0
9727       if (IS_PTR_CONST(type))
9728         genConstPointerGet (left,result,ic);
9729       else
9730 #endif
9731         genGenPointerGet (left,result,ic);
9732       break;
9733     }
9734
9735 }
9736
9737 /*-----------------------------------------------------------------*/
9738 /* genPackBits - generates code for packed bit storage             */
9739 /*-----------------------------------------------------------------*/
9740 static void genPackBits (sym_link    *etype ,
9741                          operand *right ,
9742                          char *rname, int p_type)
9743 {
9744   int shCnt = 0 ;
9745   int offset = 0  ;
9746   int rLen = 0 ;
9747   int blen, bstr ;   
9748   char *l ;
9749
9750         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9751         blen = SPEC_BLEN(etype);
9752         bstr = SPEC_BSTR(etype);
9753
9754         if(AOP_TYPE(right) == AOP_LIT) {
9755                 if((blen == 1) && (bstr < 8)) {
9756                   unsigned long lit;
9757                         /* it is a single bit, so use the appropriate bit instructions */
9758
9759                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9760
9761                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9762 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9763                         if(lit) {
9764                                 pic16_emitpcode(POC_BSF,
9765                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9766                         } else {
9767                                 pic16_emitpcode(POC_BCF,
9768                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9769                         }
9770         
9771                   return;
9772                 }
9773
9774                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9775                 offset++;
9776         } else
9777                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9778
9779         /* if the bit lenth is less than or    */
9780         /* it exactly fits a byte then         */
9781         if((shCnt=SPEC_BSTR(etype))
9782                 || SPEC_BLEN(etype) <= 8 )  {
9783
9784                 /* shift left acc */
9785                 AccLsh(shCnt);
9786
9787                 /* using PRODL as a temporary register here */
9788                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9789
9790                 switch (p_type) {
9791                         case FPOINTER:
9792                         case POINTER:
9793                         case GPOINTER:
9794                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9795 //                              pic16_emitcode ("mov","b,a");
9796 //                              pic16_emitcode("mov","a,@%s",rname);
9797                                 break;
9798                 }
9799 #if 1
9800                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9801                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9802                                         (unsigned char)(0xff >> (8-bstr))) ));
9803                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9804                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9805 #endif
9806
9807           return;
9808         }
9809
9810
9811         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9812         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9813         exit(-1);
9814
9815
9816     /* if we r done */
9817     if ( SPEC_BLEN(etype) <= 8 )
9818         return ;
9819
9820     pic16_emitcode("inc","%s",rname);
9821     rLen = SPEC_BLEN(etype) ;     
9822
9823
9824
9825     /* now generate for lengths greater than one byte */
9826     while (1) {
9827
9828         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9829
9830         rLen -= 8 ;
9831         if (rLen <= 0 )
9832             break ;
9833
9834         switch (p_type) {
9835             case POINTER:
9836                 if (*l == '@') {
9837                     MOVA(l);
9838                     pic16_emitcode("mov","@%s,a",rname);
9839                 } else
9840                     pic16_emitcode("mov","@%s,%s",rname,l);
9841                 break;
9842
9843             case FPOINTER:
9844                 MOVA(l);
9845                 pic16_emitcode("movx","@dptr,a");
9846                 break;
9847
9848             case GPOINTER:
9849                 MOVA(l);
9850                 DEBUGpic16_emitcode(";lcall","__gptrput");
9851                 break;  
9852         }   
9853         pic16_emitcode ("inc","%s",rname);
9854     }
9855
9856     MOVA(l);
9857
9858     /* last last was not complete */
9859     if (rLen)   {
9860         /* save the byte & read byte */
9861         switch (p_type) {
9862             case POINTER:
9863                 pic16_emitcode ("mov","b,a");
9864                 pic16_emitcode("mov","a,@%s",rname);
9865                 break;
9866
9867             case FPOINTER:
9868                 pic16_emitcode ("mov","b,a");
9869                 pic16_emitcode("movx","a,@dptr");
9870                 break;
9871
9872             case GPOINTER:
9873                 pic16_emitcode ("push","b");
9874                 pic16_emitcode ("push","acc");
9875                 pic16_emitcode ("lcall","__gptrget");
9876                 pic16_emitcode ("pop","b");
9877                 break;
9878         }
9879
9880         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9881         pic16_emitcode ("orl","a,b");
9882     }
9883
9884     if (p_type == GPOINTER)
9885         pic16_emitcode("pop","b");
9886
9887     switch (p_type) {
9888
9889     case POINTER:
9890         pic16_emitcode("mov","@%s,a",rname);
9891         break;
9892         
9893     case FPOINTER:
9894         pic16_emitcode("movx","@dptr,a");
9895         break;
9896         
9897     case GPOINTER:
9898         DEBUGpic16_emitcode(";lcall","__gptrput");
9899         break;                  
9900     }
9901 }
9902 /*-----------------------------------------------------------------*/
9903 /* genDataPointerSet - remat pointer to data space                 */
9904 /*-----------------------------------------------------------------*/
9905 static void genDataPointerSet(operand *right,
9906                               operand *result,
9907                               iCode *ic)
9908 {
9909     int size, offset = 0, resoffset=0 ;
9910
9911     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9912     pic16_aopOp(right,ic,FALSE);
9913
9914     size = AOP_SIZE(right);
9915
9916 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9917
9918 #if 0
9919     if ( AOP_TYPE(result) == AOP_PCODE) {
9920       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9921               AOP(result)->aopu.pcop->name,
9922                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9923               PCOR(AOP(result)->aopu.pcop)->instance:
9924               PCOI(AOP(result)->aopu.pcop)->offset);
9925     }
9926 #endif
9927
9928         if(AOP(result)->aopu.pcop->type == PO_DIR)
9929                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9930
9931         while (size--) {
9932                 if (AOP_TYPE(right) == AOP_LIT) {
9933                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9934
9935                         lit = lit >> (8*offset);
9936                         if(lit&0xff) {
9937                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9938                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9939                         } else {
9940                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9941                         }
9942                 } else {
9943                         mov2w(AOP(right), offset);
9944                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9945                 }
9946                 offset++;
9947                 resoffset++;
9948         }
9949
9950     pic16_freeAsmop(right,NULL,ic,TRUE);
9951 }
9952
9953
9954
9955 /*-----------------------------------------------------------------*/
9956 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9957 /*-----------------------------------------------------------------*/
9958 static void genNearPointerSet (operand *right,
9959                                operand *result, 
9960                                iCode *ic)
9961 {
9962   asmop *aop = NULL;
9963   char *l;
9964   sym_link *retype;
9965   sym_link *ptype = operandType(result);
9966   sym_link *resetype;
9967     
9968         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9969         retype= getSpec(operandType(right));
9970         resetype = getSpec(operandType(result));
9971   
9972         pic16_aopOp(result,ic,FALSE);
9973     
9974         /* if the result is rematerializable &
9975          * in data space & not a bit variable */
9976         
9977         /* and result is not a bit variable */
9978         if (AOP_TYPE(result) == AOP_PCODE
9979 //              && AOP_TYPE(result) == AOP_IMMD
9980                 && DCL_TYPE(ptype) == POINTER
9981                 && !IS_BITFIELD(retype)
9982                 && !IS_BITFIELD(resetype)) {
9983
9984                 genDataPointerSet (right,result,ic);
9985                 pic16_freeAsmop(result,NULL,ic,TRUE);
9986           return;
9987         }
9988
9989         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9990         pic16_aopOp(right,ic,FALSE);
9991         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9992
9993         /* if the value is already in a pointer register
9994          * then don't need anything more */
9995         if (!AOP_INPREG(AOP(result))) {
9996                 /* otherwise get a free pointer register */
9997                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9998
9999                 if( (AOP_TYPE(result) == AOP_PCODE) 
10000                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10001                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10002                 {
10003                         pic16_loadFSR0( result );  // patch 10
10004                 } else {
10005                         // set up FSR0 with address of result
10006                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10007                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10008                 }
10009
10010         }
10011 //      else
10012 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10013
10014         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10015
10016         /* if bitfield then unpack the bits */
10017         if (IS_BITFIELD(resetype)) {
10018                 genPackBits (resetype, right, NULL, POINTER);
10019         } else {
10020                 /* we have can just get the values */
10021           int size = AOP_SIZE(right);
10022           int offset = 0 ;    
10023
10024                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10025                 while (size--) {
10026                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10027                         if (*l == '@' ) {
10028                                 //MOVA(l);
10029                                 //pic16_emitcode("mov","@%s,a",rname);
10030                                 pic16_emitcode("movf","indf0,w ;1");
10031                         } else {
10032
10033                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10034                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10035                                         if (size) {                                                                     // 
10036                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10037                                         } else {                                                                        // 
10038                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10039                                         }                                                                               // 
10040                                 } else { // no literal                                                                  // 
10041                                         if(size) {                                                                      // 
10042                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10043                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10044                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10045                                         } else {                                                                        // 
10046                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10047                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10048                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10049                                         }                                                                               //
10050                                 }                                                                                       // patch 10
10051                         }
10052                         offset++;
10053                 }
10054         }
10055
10056         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10057         /* now some housekeeping stuff */
10058         if (aop) {
10059                 /* we had to allocate for this iCode */
10060                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10061         } else { 
10062                 /* we did not allocate which means left
10063                  * already in a pointer register, then
10064                  * if size > 0 && this could be used again
10065                  * we have to point it back to where it 
10066                  * belongs */
10067                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10068                 if (AOP_SIZE(right) > 1
10069                         && !OP_SYMBOL(result)->remat
10070                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10071                                 || ic->depth )) {
10072
10073                   int size = AOP_SIZE(right) - 1;
10074
10075                         while (size--)
10076                                 pic16_emitcode("decf","fsr0,f");
10077                         //pic16_emitcode("dec","%s",rname);
10078                 }
10079         }
10080
10081         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10082         /* done */
10083 //release:
10084         pic16_freeAsmop(right,NULL,ic,TRUE);
10085         pic16_freeAsmop(result,NULL,ic,TRUE);
10086 }
10087
10088 /*-----------------------------------------------------------------*/
10089 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10090 /*-----------------------------------------------------------------*/
10091 static void genPagedPointerSet (operand *right,
10092                                operand *result, 
10093                                iCode *ic)
10094 {
10095     asmop *aop = NULL;
10096     regs *preg = NULL ;
10097     char *rname , *l;
10098     sym_link *retype;
10099        
10100     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10101
10102     retype= getSpec(operandType(right));
10103     
10104     pic16_aopOp(result,ic,FALSE);
10105     
10106     /* if the value is already in a pointer register
10107        then don't need anything more */
10108     if (!AOP_INPREG(AOP(result))) {
10109         /* otherwise get a free pointer register */
10110         aop = newAsmop(0);
10111         preg = getFreePtr(ic,&aop,FALSE);
10112         pic16_emitcode("mov","%s,%s",
10113                 preg->name,
10114                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10115         rname = preg->name ;
10116     } else
10117         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10118     
10119     pic16_freeAsmop(result,NULL,ic,TRUE);
10120     pic16_aopOp (right,ic,FALSE);
10121
10122     /* if bitfield then unpack the bits */
10123     if (IS_BITFIELD(retype)) 
10124         genPackBits (retype,right,rname,PPOINTER);
10125     else {
10126         /* we have can just get the values */
10127         int size = AOP_SIZE(right);
10128         int offset = 0 ;        
10129         
10130         while (size--) {
10131             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10132             
10133             MOVA(l);
10134             pic16_emitcode("movx","@%s,a",rname);
10135
10136             if (size)
10137                 pic16_emitcode("inc","%s",rname);
10138
10139             offset++;
10140         }
10141     }
10142     
10143     /* now some housekeeping stuff */
10144     if (aop) {
10145         /* we had to allocate for this iCode */
10146         pic16_freeAsmop(NULL,aop,ic,TRUE);
10147     } else { 
10148         /* we did not allocate which means left
10149            already in a pointer register, then
10150            if size > 0 && this could be used again
10151            we have to point it back to where it 
10152            belongs */
10153         if (AOP_SIZE(right) > 1 &&
10154             !OP_SYMBOL(result)->remat &&
10155             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10156               ic->depth )) {
10157             int size = AOP_SIZE(right) - 1;
10158             while (size--)
10159                 pic16_emitcode("dec","%s",rname);
10160         }
10161     }
10162
10163     /* done */
10164     pic16_freeAsmop(right,NULL,ic,TRUE);
10165     
10166         
10167 }
10168
10169 /*-----------------------------------------------------------------*/
10170 /* genFarPointerSet - set value from far space                     */
10171 /*-----------------------------------------------------------------*/
10172 static void genFarPointerSet (operand *right,
10173                               operand *result, iCode *ic)
10174 {
10175     int size, offset ;
10176     sym_link *retype = getSpec(operandType(right));
10177
10178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10179     pic16_aopOp(result,ic,FALSE);
10180
10181     /* if the operand is already in dptr 
10182     then we do nothing else we move the value to dptr */
10183     if (AOP_TYPE(result) != AOP_STR) {
10184         /* if this is remateriazable */
10185         if (AOP_TYPE(result) == AOP_IMMD)
10186             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10187         else { /* we need to get it byte by byte */
10188             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10189             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10190             if (options.model == MODEL_FLAT24)
10191             {
10192                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10193             }
10194         }
10195     }
10196     /* so dptr know contains the address */
10197     pic16_freeAsmop(result,NULL,ic,TRUE);
10198     pic16_aopOp(right,ic,FALSE);
10199
10200     /* if bit then unpack */
10201     if (IS_BITFIELD(retype)) 
10202         genPackBits(retype,right,"dptr",FPOINTER);
10203     else {
10204         size = AOP_SIZE(right);
10205         offset = 0 ;
10206
10207         while (size--) {
10208             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10209             MOVA(l);
10210             pic16_emitcode("movx","@dptr,a");
10211             if (size)
10212                 pic16_emitcode("inc","dptr");
10213         }
10214     }
10215
10216     pic16_freeAsmop(right,NULL,ic,TRUE);
10217 }
10218
10219 /*-----------------------------------------------------------------*/
10220 /* genGenPointerSet - set value from generic pointer space         */
10221 /*-----------------------------------------------------------------*/
10222 static void genGenPointerSet (operand *right,
10223                               operand *result, iCode *ic)
10224 {
10225         int i, size, offset, lit;
10226         sym_link *retype = getSpec(operandType(right));
10227
10228         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10229
10230         pic16_aopOp(result,ic,FALSE);
10231         pic16_aopOp(right,ic,FALSE);
10232         size = AOP_SIZE(right);
10233         offset = 0;
10234
10235         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10236
10237         /* if the operand is already in dptr 
10238                 then we do nothing else we move the value to dptr */
10239         if (AOP_TYPE(result) != AOP_STR) {
10240                 /* if this is remateriazable */
10241                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10242                 // WARNING: anythig until "else" is untested!
10243                 if (AOP_TYPE(result) == AOP_IMMD) {
10244                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10245                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10246                         // load FSR0 from immediate
10247                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10248                         offset = 0;
10249                         while(size--) {
10250                                 if(size) {
10251                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10252                                 } else {
10253                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10254                                 }
10255                                 offset++;
10256                         }
10257                         goto release;
10258                 }
10259                 else { /* we need to get it byte by byte */
10260                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10261                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10262
10263                         // set up FSR0 with address of result
10264                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10265                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10266
10267                         /* hack hack! see if this the FSR. If so don't load W */
10268                         if(AOP_TYPE(right) != AOP_ACC) {
10269
10270                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10271
10272                                 if(AOP_TYPE(right) == AOP_LIT)
10273                                 {
10274                                         // copy literal
10275                                         // note: pic16_popGet handles sign extension
10276                                         for(i=0;i<size;i++) {
10277                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10278                                                 if(i < size-1)
10279                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10280                                                 else
10281                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10282                                         }
10283                                 } else {
10284                                         // copy regs
10285
10286                                         for(i=0;i<size;i++) {
10287                                                 if(i < size-1)
10288                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10289                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10290                                                 else
10291                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10292                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10293                                         }
10294                                 }
10295                                 goto release;
10296                         } 
10297                         // right = ACC
10298                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10299                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10300                         goto release;
10301         } // if (AOP_TYPE(result) != AOP_IMMD)
10302
10303         } // if (AOP_TYPE(result) != AOP_STR)
10304         /* so dptr know contains the address */
10305
10306
10307         /* if bit then unpack */
10308         if (IS_BITFIELD(retype)) 
10309                 genPackBits(retype,right,"dptr",GPOINTER);
10310         else {
10311                 size = AOP_SIZE(right);
10312                 offset = 0 ;
10313
10314                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10315
10316                 // set up FSR0 with address of result
10317                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10318                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10319         
10320                 while (size--) {
10321                         if (AOP_TYPE(right) == AOP_LIT) {
10322                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10323                                 if (size) {
10324                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10325                                 } else {
10326                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10327                                 }
10328                         } else { // no literal
10329                                 if(size) {
10330                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10331                                 } else {
10332                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10333                                 }
10334                         }
10335                         offset++;
10336                 }
10337         }
10338
10339         release:
10340         pic16_freeAsmop(right,NULL,ic,TRUE);
10341         pic16_freeAsmop(result,NULL,ic,TRUE);
10342 }
10343
10344 /*-----------------------------------------------------------------*/
10345 /* genPointerSet - stores the value into a pointer location        */
10346 /*-----------------------------------------------------------------*/
10347 static void genPointerSet (iCode *ic)
10348 {    
10349     operand *right, *result ;
10350     sym_link *type, *etype;
10351     int p_type;
10352
10353     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10354
10355     right = IC_RIGHT(ic);
10356     result = IC_RESULT(ic) ;
10357
10358     /* depending on the type of pointer we need to
10359     move it to the correct pointer register */
10360     type = operandType(result);
10361     etype = getSpec(type);
10362     /* if left is of type of pointer then it is simple */
10363     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10364         p_type = DCL_TYPE(type);
10365     }
10366     else {
10367         /* we have to go by the storage class */
10368         p_type = PTR_TYPE(SPEC_OCLS(etype));
10369
10370 /*      if (SPEC_OCLS(etype)->codesp ) { */
10371 /*          p_type = CPOINTER ;  */
10372 /*      } */
10373 /*      else */
10374 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10375 /*              p_type = FPOINTER ; */
10376 /*          else */
10377 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10378 /*                  p_type = PPOINTER ; */
10379 /*              else */
10380 /*                  if (SPEC_OCLS(etype) == idata ) */
10381 /*                      p_type = IPOINTER ; */
10382 /*                  else */
10383 /*                      p_type = POINTER ; */
10384     }
10385
10386     /* now that we have the pointer type we assign
10387     the pointer values */
10388     switch (p_type) {
10389
10390     case POINTER:
10391     case IPOINTER:
10392         genNearPointerSet (right,result,ic);
10393         break;
10394
10395     case PPOINTER:
10396         genPagedPointerSet (right,result,ic);
10397         break;
10398
10399     case FPOINTER:
10400         genFarPointerSet (right,result,ic);
10401         break;
10402
10403     case GPOINTER:
10404         genGenPointerSet (right,result,ic);
10405         break;
10406
10407     default:
10408       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10409               "genPointerSet: illegal pointer type");
10410     }
10411 }
10412
10413 /*-----------------------------------------------------------------*/
10414 /* genIfx - generate code for Ifx statement                        */
10415 /*-----------------------------------------------------------------*/
10416 static void genIfx (iCode *ic, iCode *popIc)
10417 {
10418   operand *cond = IC_COND(ic);
10419   int isbit =0;
10420
10421   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10422
10423   pic16_aopOp(cond,ic,FALSE);
10424
10425   /* get the value into acc */
10426   if (AOP_TYPE(cond) != AOP_CRY)
10427     pic16_toBoolean(cond);
10428   else
10429     isbit = 1;
10430   /* the result is now in the accumulator */
10431   pic16_freeAsmop(cond,NULL,ic,TRUE);
10432
10433   /* if there was something to be popped then do it */
10434   if (popIc)
10435     genIpop(popIc);
10436
10437   /* if the condition is  a bit variable */
10438   if (isbit && IS_ITEMP(cond) && 
10439       SPIL_LOC(cond)) {
10440     genIfxJump(ic,SPIL_LOC(cond)->rname);
10441     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10442   }
10443   else {
10444     if (isbit && !IS_ITEMP(cond))
10445       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10446     else
10447       genIfxJump(ic,"a");
10448   }
10449   ic->generated = 1;
10450
10451 }
10452
10453 /*-----------------------------------------------------------------*/
10454 /* genAddrOf - generates code for address of                       */
10455 /*-----------------------------------------------------------------*/
10456 static void genAddrOf (iCode *ic)
10457 {
10458   operand *result, *left;
10459   int size;
10460   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10461   pCodeOp *pcop0, *pcop1, *pcop2;
10462
10463         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10464
10465         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10466         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10467
10468         sym = OP_SYMBOL( left );
10469
10470         size = AOP_SIZE(IC_RESULT(ic));
10471
10472 //      if(pic16_debug_verbose) {
10473 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10474 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10475 //      }
10476         
10477         /* Assume that what we want the address of is in data space
10478          * since there is no stack on the PIC, yet! -- VR */
10479         /* low */
10480         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10481
10482         /* high */
10483         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10484         
10485         /* upper */
10486         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10487         
10488
10489         if (size == 3) {
10490                 pic16_emitpcode(POC_MOVLW, pcop0);
10491                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10492                 pic16_emitpcode(POC_MOVLW, pcop1);
10493                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10494                 pic16_emitpcode(POC_MOVLW, pcop2);
10495                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10496         } else
10497         if (size == 2) {
10498                 pic16_emitpcode(POC_MOVLW, pcop0);
10499                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10500                 pic16_emitpcode(POC_MOVLW, pcop1);
10501                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10502         } else {
10503                 pic16_emitpcode(POC_MOVLW, pcop0);
10504                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10505         }
10506
10507         pic16_freeAsmop(result,NULL,ic,TRUE);
10508         pic16_freeAsmop(left, NULL, ic, FALSE);
10509 }
10510
10511
10512 #if 0
10513 /*-----------------------------------------------------------------*/
10514 /* genFarFarAssign - assignment when both are in far space         */
10515 /*-----------------------------------------------------------------*/
10516 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10517 {
10518     int size = AOP_SIZE(right);
10519     int offset = 0;
10520     char *l ;
10521     /* first push the right side on to the stack */
10522     while (size--) {
10523         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10524         MOVA(l);
10525         pic16_emitcode ("push","acc");
10526     }
10527     
10528     pic16_freeAsmop(right,NULL,ic,FALSE);
10529     /* now assign DPTR to result */
10530     pic16_aopOp(result,ic,FALSE);
10531     size = AOP_SIZE(result);
10532     while (size--) {
10533         pic16_emitcode ("pop","acc");
10534         pic16_aopPut(AOP(result),"a",--offset);
10535     }
10536     pic16_freeAsmop(result,NULL,ic,FALSE);
10537         
10538 }
10539 #endif
10540
10541 /*-----------------------------------------------------------------*/
10542 /* genAssign - generate code for assignment                        */
10543 /*-----------------------------------------------------------------*/
10544 static void genAssign (iCode *ic)
10545 {
10546   operand *result, *right;
10547   int size, offset,know_W;
10548   unsigned long lit = 0L;
10549
10550   result = IC_RESULT(ic);
10551   right  = IC_RIGHT(ic) ;
10552
10553   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10554   
10555   /* if they are the same */
10556   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10557     return ;
10558
10559   pic16_aopOp(right,ic,FALSE);
10560   pic16_aopOp(result,ic,TRUE);
10561
10562   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10563
10564   /* if they are the same registers */
10565   if (pic16_sameRegs(AOP(right),AOP(result)))
10566     goto release;
10567
10568   /* if the result is a bit */
10569   if (AOP_TYPE(result) == AOP_CRY) {
10570     /* if the right size is a literal then
10571        we know what the value is */
10572     if (AOP_TYPE(right) == AOP_LIT) {
10573           
10574       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10575                   pic16_popGet(AOP(result),0));
10576
10577       if (((int) operandLitValue(right))) 
10578         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10579                        AOP(result)->aopu.aop_dir,
10580                        AOP(result)->aopu.aop_dir);
10581       else
10582         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10583                        AOP(result)->aopu.aop_dir,
10584                        AOP(result)->aopu.aop_dir);
10585       goto release;
10586     }
10587
10588     /* the right is also a bit variable */
10589     if (AOP_TYPE(right) == AOP_CRY) {
10590       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10591       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10592       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10593
10594       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10595                      AOP(result)->aopu.aop_dir,
10596                      AOP(result)->aopu.aop_dir);
10597       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10598                      AOP(right)->aopu.aop_dir,
10599                      AOP(right)->aopu.aop_dir);
10600       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10601                      AOP(result)->aopu.aop_dir,
10602                      AOP(result)->aopu.aop_dir);
10603       goto release ;
10604     }
10605
10606     /* we need to or */
10607     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10608     pic16_toBoolean(right);
10609     emitSKPZ;
10610     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10611     //pic16_aopPut(AOP(result),"a",0);
10612     goto release ;
10613   }
10614
10615   /* bit variables done */
10616   /* general case */
10617   size = AOP_SIZE(result);
10618   offset = 0 ;
10619
10620   if(AOP_TYPE(right) == AOP_LIT) {
10621         if(!IS_FLOAT(operandType( right )))
10622                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10623         else {
10624            union {
10625               unsigned long lit_int;
10626               float lit_float;
10627             } info;
10628         
10629                 /* take care if literal is a float */
10630                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10631                 lit = info.lit_int;
10632         }
10633   }
10634
10635 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10636 //                      sizeof(unsigned long int), sizeof(float));
10637
10638   if(AOP_TYPE(right) != AOP_LIT
10639         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10640         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10641
10642         // set up table pointer
10643         if( (AOP_TYPE(right) == AOP_PCODE)
10644                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10645                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10646         {
10647                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10648                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10649                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10650                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10651                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10652                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10653         } else {
10654                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10655                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10656                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10657                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10658                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10659                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10660         }
10661
10662         size = min(AOP_SIZE(right), AOP_SIZE(result));
10663         while(size--) {
10664                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10665                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10666                         pic16_popGet(AOP(result),offset)));
10667                 offset++;
10668         }
10669
10670         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10671                 size = AOP_SIZE(result) - AOP_SIZE(right);
10672                 while(size--) {
10673                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10674                         offset++;
10675                 }
10676         }
10677         goto release;
10678   }
10679
10680
10681
10682 /* VR - What is this?! */
10683   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10684   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10685     if(aopIdx(AOP(result),0) == 4) {
10686   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10687         assert(0);
10688       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10689       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10690       goto release;
10691     } else
10692 //      assert(0);
10693       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10694   }
10695
10696   know_W=-1;
10697   while (size--) {
10698   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10699     if(AOP_TYPE(right) == AOP_LIT) {
10700       if(lit&0xff) {
10701         if(know_W != (lit&0xff))
10702           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10703         know_W = lit&0xff;
10704         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10705       } else
10706         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10707
10708       lit >>= 8;
10709
10710     } else if (AOP_TYPE(right) == AOP_CRY) {
10711       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10712       if(offset == 0) {
10713         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10714         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10715       }
10716     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10717         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10718         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10719     } else {
10720   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10721
10722 #if 1
10723         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10724            normally should work, but mind that the W register live range
10725            is not checked, so if the code generator assumes that the W
10726            is already loaded after such a pair, wrong code will be generated.
10727            
10728            Checking the live range is the next step.
10729            This is experimental code yet and has not been fully tested yet.
10730            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10731            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10732            
10733         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10734 #else   
10735         /* This is the old code, which is assumed(?!) that works fine(!?) */
10736
10737         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10738         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10739 #endif
10740     }
10741             
10742     offset++;
10743   }
10744
10745     
10746  release:
10747   pic16_freeAsmop (right,NULL,ic,FALSE);
10748   pic16_freeAsmop (result,NULL,ic,TRUE);
10749 }   
10750
10751 /*-----------------------------------------------------------------*/
10752 /* genJumpTab - generates code for jump table                       */
10753 /*-----------------------------------------------------------------*/
10754 static void genJumpTab (iCode *ic)
10755 {
10756     symbol *jtab;
10757     char *l;
10758
10759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10760
10761     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10762     /* get the condition into accumulator */
10763     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10764     MOVA(l);
10765     /* multiply by three */
10766     pic16_emitcode("add","a,acc");
10767     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10768
10769     jtab = newiTempLabel(NULL);
10770     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10771     pic16_emitcode("jmp","@a+dptr");
10772     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10773
10774     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10775     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10776     emitSKPNC;
10777     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10778     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10779     pic16_emitpLabel(jtab->key);
10780
10781     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10782
10783     /* now generate the jump labels */
10784     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10785          jtab = setNextItem(IC_JTLABELS(ic))) {
10786         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10787         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10788         
10789     }
10790
10791 }
10792
10793 /*-----------------------------------------------------------------*/
10794 /* genMixedOperation - gen code for operators between mixed types  */
10795 /*-----------------------------------------------------------------*/
10796 /*
10797   TSD - Written for the PIC port - but this unfortunately is buggy.
10798   This routine is good in that it is able to efficiently promote 
10799   types to different (larger) sizes. Unfortunately, the temporary
10800   variables that are optimized out by this routine are sometimes
10801   used in other places. So until I know how to really parse the 
10802   iCode tree, I'm going to not be using this routine :(.
10803 */
10804 static int genMixedOperation (iCode *ic)
10805 {
10806 #if 0
10807   operand *result = IC_RESULT(ic);
10808   sym_link *ctype = operandType(IC_LEFT(ic));
10809   operand *right = IC_RIGHT(ic);
10810   int ret = 0;
10811   int big,small;
10812   int offset;
10813
10814   iCode *nextic;
10815   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10816
10817   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10818
10819   nextic = ic->next;
10820   if(!nextic)
10821     return 0;
10822
10823   nextright = IC_RIGHT(nextic);
10824   nextleft  = IC_LEFT(nextic);
10825   nextresult = IC_RESULT(nextic);
10826
10827   pic16_aopOp(right,ic,FALSE);
10828   pic16_aopOp(result,ic,FALSE);
10829   pic16_aopOp(nextright,  nextic, FALSE);
10830   pic16_aopOp(nextleft,   nextic, FALSE);
10831   pic16_aopOp(nextresult, nextic, FALSE);
10832
10833   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10834
10835     operand *t = right;
10836     right = nextright;
10837     nextright = t; 
10838
10839     pic16_emitcode(";remove right +","");
10840
10841   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10842 /*
10843     operand *t = right;
10844     right = nextleft;
10845     nextleft = t; 
10846 */
10847     pic16_emitcode(";remove left +","");
10848   } else
10849     return 0;
10850
10851   big = AOP_SIZE(nextleft);
10852   small = AOP_SIZE(nextright);
10853
10854   switch(nextic->op) {
10855
10856   case '+':
10857     pic16_emitcode(";optimize a +","");
10858     /* if unsigned or not an integral type */
10859     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10860       pic16_emitcode(";add a bit to something","");
10861     } else {
10862
10863       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10864
10865       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10866         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10867         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10868       } else
10869         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10870
10871       offset = 0;
10872       while(--big) {
10873
10874         offset++;
10875
10876         if(--small) {
10877           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10878             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10879             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10880           }
10881
10882           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10883           emitSKPNC;
10884           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10885                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10886                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10887           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10888           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10889
10890         } else {
10891           pic16_emitcode("rlf","known_zero,w");
10892
10893           /*
10894             if right is signed
10895               btfsc  right,7
10896                addlw ff
10897           */
10898           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10899             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10900             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10901           } else {
10902             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10903           }
10904         }
10905       }
10906       ret = 1;
10907     }
10908   }
10909   ret = 1;
10910
10911 release:
10912   pic16_freeAsmop(right,NULL,ic,TRUE);
10913   pic16_freeAsmop(result,NULL,ic,TRUE);
10914   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10915   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10916   if(ret)
10917     nextic->generated = 1;
10918
10919   return ret;
10920 #else
10921   return 0;
10922 #endif
10923 }
10924 /*-----------------------------------------------------------------*/
10925 /* genCast - gen code for casting                                  */
10926 /*-----------------------------------------------------------------*/
10927 static void genCast (iCode *ic)
10928 {
10929   operand *result = IC_RESULT(ic);
10930   sym_link *ctype = operandType(IC_LEFT(ic));
10931   sym_link *rtype = operandType(IC_RIGHT(ic));
10932   operand *right = IC_RIGHT(ic);
10933   int size, offset ;
10934
10935         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10936         /* if they are equivalent then do nothing */
10937         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10938                 return ;
10939
10940         pic16_aopOp(right,ic,FALSE) ;
10941         pic16_aopOp(result,ic,FALSE);
10942
10943         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10944
10945         /* if the result is a bit */
10946         if (AOP_TYPE(result) == AOP_CRY) {
10947         
10948                 /* if the right size is a literal then
10949                  * we know what the value is */
10950                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10951
10952                 if (AOP_TYPE(right) == AOP_LIT) {
10953                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10954                                 pic16_popGet(AOP(result),0));
10955
10956                         if (((int) operandLitValue(right))) 
10957                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10958                                         AOP(result)->aopu.aop_dir,
10959                                         AOP(result)->aopu.aop_dir);
10960                         else
10961                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10962                                         AOP(result)->aopu.aop_dir,
10963                                         AOP(result)->aopu.aop_dir);
10964                         goto release;
10965                 }
10966
10967                 /* the right is also a bit variable */
10968                 if (AOP_TYPE(right) == AOP_CRY) {
10969                         emitCLRC;
10970                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10971
10972                         pic16_emitcode("clrc","");
10973                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10974                                 AOP(right)->aopu.aop_dir,
10975                                 AOP(right)->aopu.aop_dir);
10976                         pic16_aopPut(AOP(result),"c",0);
10977                         goto release ;
10978                 }
10979
10980                 /* we need to or */
10981                 if (AOP_TYPE(right) == AOP_REG) {
10982                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10983                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10984                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10985                 }
10986                 pic16_toBoolean(right);
10987                 pic16_aopPut(AOP(result),"a",0);
10988                 goto release ;
10989         }
10990
10991         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10992           int offset = 1;
10993
10994                 size = AOP_SIZE(result);
10995
10996                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10997
10998                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10999                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11000                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11001
11002                 while (size--)
11003                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11004
11005                 goto release;
11006         }
11007
11008         /* if they are the same size : or less */
11009         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11010
11011                 /* if they are in the same place */
11012                 if (pic16_sameRegs(AOP(right),AOP(result)))
11013                         goto release;
11014
11015                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11016 #if 0
11017                 if (IS_PTR_CONST(rtype))
11018 #else
11019                 if (IS_CODEPTR(rtype))
11020 #endif
11021                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11022
11023 #if 0
11024                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11025 #else
11026                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11027 #endif
11028                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11029
11030 #if 0
11031                 if(AOP_TYPE(right) == AOP_IMMD) {
11032                   pCodeOp *pcop0, *pcop1, *pcop2;
11033                   symbol *sym = OP_SYMBOL( right );
11034
11035                         size = AOP_SIZE(result);
11036                         /* low */
11037                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11038                         /* high */
11039                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11040                         /* upper */
11041                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11042         
11043                         if (size == 3) {
11044                                 pic16_emitpcode(POC_MOVLW, pcop0);
11045                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11046                                 pic16_emitpcode(POC_MOVLW, pcop1);
11047                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11048                                 pic16_emitpcode(POC_MOVLW, pcop2);
11049                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11050                         } else
11051                         if (size == 2) {
11052                                 pic16_emitpcode(POC_MOVLW, pcop0);
11053                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11054                                 pic16_emitpcode(POC_MOVLW, pcop1);
11055                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11056                         } else {
11057                                 pic16_emitpcode(POC_MOVLW, pcop0);
11058                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11059                         }
11060                 } else
11061 #endif
11062                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11063                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11064                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11065                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11066                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11067                         if(AOP_SIZE(result) <2)
11068                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11069                 } else {
11070                         /* if they in different places then copy */
11071                         size = AOP_SIZE(result);
11072                         offset = 0 ;
11073                         while (size--) {
11074                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11075                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11076                                 offset++;
11077                         }
11078                 }
11079                 goto release;
11080         }
11081
11082         /* if the result is of type pointer */
11083         if (IS_PTR(ctype)) {
11084           int p_type;
11085           sym_link *type = operandType(right);
11086           sym_link *etype = getSpec(type);
11087
11088                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11089
11090                 /* pointer to generic pointer */
11091                 if (IS_GENPTR(ctype)) {
11092                   char *l = zero;
11093             
11094                         if (IS_PTR(type)) 
11095                                 p_type = DCL_TYPE(type);
11096                         else {
11097                 /* we have to go by the storage class */
11098                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11099
11100 /*              if (SPEC_OCLS(etype)->codesp )  */
11101 /*                  p_type = CPOINTER ;  */
11102 /*              else */
11103 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11104 /*                      p_type = FPOINTER ; */
11105 /*                  else */
11106 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11107 /*                          p_type = PPOINTER; */
11108 /*                      else */
11109 /*                          if (SPEC_OCLS(etype) == idata ) */
11110 /*                              p_type = IPOINTER ; */
11111 /*                          else */
11112 /*                              p_type = POINTER ; */
11113             }
11114                 
11115             /* the first two bytes are known */
11116       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11117             size = GPTRSIZE - 1; 
11118             offset = 0 ;
11119             while (size--) {
11120               if(offset < AOP_SIZE(right)) {
11121       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11122                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11123                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11124                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11125                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11126                 } else { 
11127                   pic16_aopPut(AOP(result),
11128                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11129                          offset);
11130                 }
11131               } else 
11132                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11133               offset++;
11134             }
11135             /* the last byte depending on type */
11136             switch (p_type) {
11137             case IPOINTER:
11138             case POINTER:
11139                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11140                 break;
11141             case FPOINTER:
11142               pic16_emitcode(";BUG!? ","%d",__LINE__);
11143                 l = one;
11144                 break;
11145             case CPOINTER:
11146               pic16_emitcode(";BUG!? ","%d",__LINE__);
11147                 l = "#0x02";
11148                 break;                          
11149             case PPOINTER:
11150               pic16_emitcode(";BUG!? ","%d",__LINE__);
11151                 l = "#0x03";
11152                 break;
11153                 
11154             default:
11155                 /* this should never happen */
11156                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11157                        "got unknown pointer type");
11158                 exit(1);
11159             }
11160             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11161             goto release ;
11162         }
11163         
11164         /* just copy the pointers */
11165         size = AOP_SIZE(result);
11166         offset = 0 ;
11167         while (size--) {
11168             pic16_aopPut(AOP(result),
11169                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11170                    offset);
11171             offset++;
11172         }
11173         goto release ;
11174     }
11175     
11176
11177
11178     /* so we now know that the size of destination is greater
11179     than the size of the source.
11180     Now, if the next iCode is an operator then we might be
11181     able to optimize the operation without performing a cast.
11182     */
11183     if(genMixedOperation(ic))
11184       goto release;
11185
11186     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11187     
11188     /* we move to result for the size of source */
11189     size = AOP_SIZE(right);
11190     offset = 0 ;
11191     while (size--) {
11192       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11193       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11194       offset++;
11195     }
11196
11197     /* now depending on the sign of the destination */
11198     size = AOP_SIZE(result) - AOP_SIZE(right);
11199     /* if unsigned or not an integral type */
11200     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11201       while (size--)
11202         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11203     } else {
11204       /* we need to extend the sign :( */
11205
11206       if(size == 1) {
11207         /* Save one instruction of casting char to int */
11208         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11209         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11210         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11211       } else {
11212         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11213
11214         if(offset)
11215           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11216         else
11217           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11218         
11219         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11220
11221         while (size--)
11222           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11223       }
11224     }
11225
11226 release:
11227     pic16_freeAsmop(right,NULL,ic,TRUE);
11228     pic16_freeAsmop(result,NULL,ic,TRUE);
11229
11230 }
11231
11232 /*-----------------------------------------------------------------*/
11233 /* genDjnz - generate decrement & jump if not zero instrucion      */
11234 /*-----------------------------------------------------------------*/
11235 static int genDjnz (iCode *ic, iCode *ifx)
11236 {
11237     symbol *lbl, *lbl1;
11238     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11239
11240     if (!ifx)
11241         return 0;
11242     
11243     /* if the if condition has a false label
11244        then we cannot save */
11245     if (IC_FALSE(ifx))
11246         return 0;
11247
11248     /* if the minus is not of the form 
11249        a = a - 1 */
11250     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11251         !IS_OP_LITERAL(IC_RIGHT(ic)))
11252         return 0;
11253
11254     if (operandLitValue(IC_RIGHT(ic)) != 1)
11255         return 0;
11256
11257     /* if the size of this greater than one then no
11258        saving */
11259     if (getSize(operandType(IC_RESULT(ic))) > 1)
11260         return 0;
11261
11262     /* otherwise we can save BIG */
11263     lbl = newiTempLabel(NULL);
11264     lbl1= newiTempLabel(NULL);
11265
11266     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11267     
11268     if (IS_AOP_PREG(IC_RESULT(ic))) {
11269         pic16_emitcode("dec","%s",
11270                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11271         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11272         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11273     } else {    
11274
11275
11276       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11277       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11278
11279       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11280       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11281
11282     }
11283 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11284 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11285 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11286 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11287
11288     
11289     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11290     ifx->generated = 1;
11291     return 1;
11292 }
11293
11294 /*-----------------------------------------------------------------*/
11295 /* genReceive - generate code for a receive iCode                  */
11296 /*-----------------------------------------------------------------*/
11297 static void genReceive (iCode *ic)
11298 {    
11299         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11300
11301         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11302                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11303                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11304
11305           int size = getSize(operandType(IC_RESULT(ic)));
11306           int offset =  pic16_fReturnSizePic - size;
11307
11308                 while (size--) {
11309                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11310                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11311                         offset++;
11312                 }
11313
11314                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11315
11316                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11317                 size = AOP_SIZE(IC_RESULT(ic));
11318                 offset = 0;
11319                 while (size--) {
11320                         pic16_emitcode ("pop","acc");
11321                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11322                 }
11323         } else {
11324                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11325
11326                 _G.accInUse++;
11327                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11328                 _G.accInUse--;
11329                 assignResultValue(IC_RESULT(ic), 0);
11330         }
11331
11332         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11333 }
11334
11335 /*-----------------------------------------------------------------*/
11336 /* genDummyRead - generate code for dummy read of volatiles        */
11337 /*-----------------------------------------------------------------*/
11338 static void
11339 genDummyRead (iCode * ic)
11340 {
11341   pic16_emitcode ("; genDummyRead","");
11342   pic16_emitcode ("; not implemented","");
11343
11344   ic = ic;
11345 }
11346
11347 /*-----------------------------------------------------------------*/
11348 /* genpic16Code - generate code for pic16 based controllers        */
11349 /*-----------------------------------------------------------------*/
11350 /*
11351  * At this point, ralloc.c has gone through the iCode and attempted
11352  * to optimize in a way suitable for a PIC. Now we've got to generate
11353  * PIC instructions that correspond to the iCode.
11354  *
11355  * Once the instructions are generated, we'll pass through both the
11356  * peep hole optimizer and the pCode optimizer.
11357  *-----------------------------------------------------------------*/
11358
11359 void genpic16Code (iCode *lic)
11360 {
11361     iCode *ic;
11362     int cln = 0;
11363
11364     lineHead = lineCurr = NULL;
11365
11366     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11367     pic16_addpBlock(pb);
11368
11369 #if 0
11370     /* if debug information required */
11371     if (options.debug && currFunc) {
11372       if (currFunc) {
11373         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11374       }
11375     }
11376 #endif
11377
11378     for (ic = lic ; ic ; ic = ic->next ) {
11379
11380       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11381         if ( cln != ic->lineno ) {
11382             if ( options.debug ) {
11383               debugFile->writeCLine (ic);
11384             }
11385             
11386             if(!options.noCcodeInAsm) {
11387                 pic16_addpCode2pBlock(pb,
11388                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11389                                 printCLine(ic->filename, ic->lineno)));
11390             }
11391
11392             cln = ic->lineno ;
11393         }
11394         
11395         if(options.iCodeInAsm) {
11396                 char *l;
11397                 /* insert here code to print iCode as comment */
11398                 l = Safe_strdup(printILine(ic));
11399                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11400         }
11401         
11402         /* if the result is marked as
11403            spilt and rematerializable or code for
11404            this has already been generated then
11405            do nothing */
11406         if (resultRemat(ic) || ic->generated ) 
11407             continue ;
11408         
11409         /* depending on the operation */
11410         switch (ic->op) {
11411         case '!' :
11412             pic16_genNot(ic);
11413             break;
11414             
11415         case '~' :
11416             pic16_genCpl(ic);
11417             break;
11418             
11419         case UNARYMINUS:
11420             genUminus (ic);
11421             break;
11422             
11423         case IPUSH:
11424             genIpush (ic);
11425             break;
11426             
11427         case IPOP:
11428             /* IPOP happens only when trying to restore a 
11429                spilt live range, if there is an ifx statement
11430                following this pop then the if statement might
11431                be using some of the registers being popped which
11432                would destroy the contents of the register so
11433                we need to check for this condition and handle it */
11434             if (ic->next            && 
11435                 ic->next->op == IFX &&
11436                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11437                 genIfx (ic->next,ic);
11438             else
11439                 genIpop (ic);
11440             break; 
11441             
11442         case CALL:
11443             genCall (ic);
11444             break;
11445             
11446         case PCALL:
11447             genPcall (ic);
11448             break;
11449             
11450         case FUNCTION:
11451             genFunction (ic);
11452             break;
11453             
11454         case ENDFUNCTION:
11455             genEndFunction (ic);
11456             break;
11457             
11458         case RETURN:
11459             genRet (ic);
11460             break;
11461             
11462         case LABEL:
11463             genLabel (ic);
11464             break;
11465             
11466         case GOTO:
11467             genGoto (ic);
11468             break;
11469             
11470         case '+' :
11471             pic16_genPlus (ic) ;
11472             break;
11473             
11474         case '-' :
11475             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11476                 pic16_genMinus (ic);
11477             break;
11478             
11479         case '*' :
11480             genMult (ic);
11481             break;
11482             
11483         case '/' :
11484             genDiv (ic) ;
11485             break;
11486             
11487         case '%' :
11488             genMod (ic);
11489             break;
11490             
11491         case '>' :
11492             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11493             break;
11494             
11495         case '<' :
11496             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11497             break;
11498             
11499         case LE_OP:
11500         case GE_OP:
11501         case NE_OP:
11502             
11503             /* note these two are xlated by algebraic equivalence
11504                during parsing SDCC.y */
11505             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11506                    "got '>=' or '<=' shouldn't have come here");
11507             break;      
11508             
11509         case EQ_OP:
11510             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11511             break;          
11512             
11513         case AND_OP:
11514             genAndOp (ic);
11515             break;
11516             
11517         case OR_OP:
11518             genOrOp (ic);
11519             break;
11520             
11521         case '^' :
11522             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11523             break;
11524             
11525         case '|' :
11526                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11527             break;
11528             
11529         case BITWISEAND:
11530             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11531             break;
11532             
11533         case INLINEASM:
11534             genInline (ic);
11535             break;
11536             
11537         case RRC:
11538             genRRC (ic);
11539             break;
11540             
11541         case RLC:
11542             genRLC (ic);
11543             break;
11544             
11545         case GETHBIT:
11546             genGetHbit (ic);
11547             break;
11548             
11549         case LEFT_OP:
11550             genLeftShift (ic);
11551             break;
11552             
11553         case RIGHT_OP:
11554             genRightShift (ic);
11555             break;
11556             
11557         case GET_VALUE_AT_ADDRESS:
11558             genPointerGet(ic);
11559             break;
11560             
11561         case '=' :
11562             if (POINTER_SET(ic))
11563                 genPointerSet(ic);
11564             else
11565                 genAssign(ic);
11566             break;
11567             
11568         case IFX:
11569             genIfx (ic,NULL);
11570             break;
11571             
11572         case ADDRESS_OF:
11573             genAddrOf (ic);
11574             break;
11575             
11576         case JUMPTABLE:
11577             genJumpTab (ic);
11578             break;
11579             
11580         case CAST:
11581             genCast (ic);
11582             break;
11583             
11584         case RECEIVE:
11585             genReceive(ic);
11586             break;
11587             
11588         case SEND:
11589             addSet(&_G.sendSet,ic);
11590             break;
11591
11592         case DUMMY_READ_VOLATILE:
11593           genDummyRead (ic);
11594           break;
11595
11596         default :
11597             ic = ic;
11598         }
11599     }
11600
11601
11602     /* now we are ready to call the
11603        peep hole optimizer */
11604     if (!options.nopeep) {
11605       peepHole (&lineHead);
11606     }
11607     /* now do the actual printing */
11608     printLine (lineHead,codeOutFile);
11609
11610 #ifdef PCODE_DEBUG
11611     DFPRINTF((stderr,"printing pBlock\n\n"));
11612     pic16_printpBlock(stdout,pb);
11613 #endif
11614
11615     return;
11616 }
11617