2004-03-03 Hans Dorn <hjdorn AT users.sourceforge.net>
[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   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 void pic16_pushpCodeOp(pCodeOp *pcop);
81 void pic16_poppCodeOp(pCodeOp *pcop);
82
83
84
85 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
86
87 /* this is the down and dirty file with all kinds of 
88    kludgy & hacky stuff. This is what it is all about
89    CODE GENERATION for a specific MCU . some of the
90    routines may be reusable, will have to see */
91
92 static char *zero = "#0x00";
93 static char *one  = "#0x01";
94 static char *spname = "sp";
95
96
97 /*
98  * Function return value policy (MSB-->LSB):
99  *  8 bits      -> WREG
100  * 16 bits      -> PRODL:WREG
101  * 24 bits      -> PRODH:PRODL:WREG
102  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
103  * >32 bits     -> on stack, and FSR0 points to the beginning
104  *
105  */
106  
107
108 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
109 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
110 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
111 static char **fReturn = fReturnpic16;
112
113 static char *accUse[] = {"WREG"};
114
115 //static short rbank = -1;
116
117 static struct {
118     short r0Pushed;
119     short r1Pushed;
120     short accInUse;
121     short inLine;
122     short debugLine;
123     short nRegsSaved;
124     set *sendSet;
125     int interruptvector;
126 } _G;
127
128 /* Resolved ifx structure. This structure stores information
129    about an iCode ifx that makes it easier to generate code.
130 */
131 typedef struct resolvedIfx {
132   symbol *lbl;     /* pointer to a label */
133   int condition;   /* true or false ifx */
134   int generated;   /* set true when the code associated with the ifx
135                     * is generated */
136 } resolvedIfx;
137
138 extern int pic16_ptrRegReq ;
139 extern int pic16_nRegs;
140 extern FILE *codeOutFile;
141 static void saverbank (int, iCode *,bool);
142
143 static lineNode *lineHead = NULL;
144 static lineNode *lineCurr = NULL;
145
146 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
147 0xE0, 0xC0, 0x80, 0x00};
148 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
149 0x07, 0x03, 0x01, 0x00};
150
151 static  pBlock *pb;
152
153 /*-----------------------------------------------------------------*/
154 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
155 /*                 exponent of 2 is returned, otherwise -1 is      */
156 /*                 returned.                                       */
157 /* note that this is similar to the function `powof2' in SDCCsymt  */
158 /* if(n == 2^y)                                                    */
159 /*   return y;                                                     */
160 /* return -1;                                                      */
161 /*-----------------------------------------------------------------*/
162 static int my_powof2 (unsigned long num)
163 {
164   if(num) {
165     if( (num & (num-1)) == 0) {
166       int nshifts = -1;
167       while(num) {
168         num>>=1;
169         nshifts++;
170       }
171       return nshifts;
172     }
173   }
174
175   return -1;
176 }
177
178 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
179 {
180   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
181                        line_no,
182                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
183                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
184                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
185                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
186                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
187                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
188                        ((result) ? AOP_SIZE(result) : 0));
189 }
190
191 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
192 {
193
194   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
195                        line_no,
196                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
197                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
198                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
199                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
200                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
201                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
202
203 }
204
205 void pic16_emitpcomment (char *fmt, ...)
206 {
207     va_list ap;
208     char lb[INITIAL_INLINEASM];  
209     char *lbp = lb;
210
211     va_start(ap,fmt);   
212
213     lb[0] = ';';
214     vsprintf(lb+1,fmt,ap);
215
216     while (isspace(*lbp)) lbp++;
217
218     if (lbp && *lbp) 
219         lineCurr = (lineCurr ?
220                     connectLine(lineCurr,newLineNode(lb)) :
221                     (lineHead = newLineNode(lb)));
222     lineCurr->isInline = _G.inLine;
223     lineCurr->isDebug  = _G.debugLine;
224
225     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
226     va_end(ap);
227
228 //      fprintf(stderr, "%s\n", lb);
229 }
230
231 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
232 {
233     va_list ap;
234     char lb[INITIAL_INLINEASM];  
235     char *lbp = lb;
236
237     if(!pic16_debug_verbose)
238       return;
239
240     va_start(ap,fmt);   
241
242     if (inst && *inst) {
243         if (fmt && *fmt)
244             sprintf(lb,"%s\t",inst);
245         else
246             sprintf(lb,"%s",inst);
247         vsprintf(lb+(strlen(lb)),fmt,ap);
248     }  else
249         vsprintf(lb,fmt,ap);
250
251     while (isspace(*lbp)) lbp++;
252
253     if (lbp && *lbp) 
254         lineCurr = (lineCurr ?
255                     connectLine(lineCurr,newLineNode(lb)) :
256                     (lineHead = newLineNode(lb)));
257     lineCurr->isInline = _G.inLine;
258     lineCurr->isDebug  = _G.debugLine;
259
260     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
261     va_end(ap);
262
263 //      fprintf(stderr, "%s\n", lb);
264 }
265
266 void pic16_emitpLabel(int key)
267 {
268   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
269 }
270
271 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
272 {
273
274   if(pcop)
275     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
276   else
277     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
278     
279 //    fprintf(stderr, "%s\n", pcop->name);
280 }
281
282 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
283 {
284
285   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
286
287 }
288
289
290 #if 1
291 #define pic16_emitcode  DEBUGpic16_emitcode
292 #else
293 /*-----------------------------------------------------------------*/
294 /* pic16_emitcode - writes the code into a file : for now it is simple    */
295 /*-----------------------------------------------------------------*/
296 void pic16_emitcode (char *inst,char *fmt, ...)
297 {
298     va_list ap;
299     char lb[INITIAL_INLINEASM];  
300     char *lbp = lb;
301
302     va_start(ap,fmt);   
303
304     if (inst && *inst) {
305         if (fmt && *fmt)
306             sprintf(lb,"%s\t",inst);
307         else
308             sprintf(lb,"%s",inst);
309         vsprintf(lb+(strlen(lb)),fmt,ap);
310     }  else
311         vsprintf(lb,fmt,ap);
312
313     while (isspace(*lbp)) lbp++;
314
315     if (lbp && *lbp) 
316         lineCurr = (lineCurr ?
317                     connectLine(lineCurr,newLineNode(lb)) :
318                     (lineHead = newLineNode(lb)));
319     lineCurr->isInline = _G.inLine;
320     lineCurr->isDebug  = _G.debugLine;
321
322 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
323
324 //    if(pic16_debug_verbose)
325 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
326
327     va_end(ap);
328 }
329 #endif
330
331
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
334 /*-----------------------------------------------------------------*/
335 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
336 {
337     bool r0iu = FALSE , r1iu = FALSE;
338     bool r0ou = FALSE , r1ou = FALSE;
339
340         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
341
342     /* the logic: if r0 & r1 used in the instruction
343     then we are in trouble otherwise */
344
345     /* first check if r0 & r1 are used by this
346     instruction, in which case we are in trouble */
347     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
348         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
349     {
350         goto endOfWorld;      
351     }
352
353     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
354     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
355
356     /* if no usage of r0 then return it */
357     if (!r0iu && !r0ou) {
358         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
359         (*aopp)->type = AOP_R0;
360         
361         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
362     }
363
364     /* if no usage of r1 then return it */
365     if (!r1iu && !r1ou) {
366         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
367         (*aopp)->type = AOP_R1;
368
369         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
370     }    
371
372     /* now we know they both have usage */
373     /* if r0 not used in this instruction */
374     if (!r0iu) {
375         /* push it if not already pushed */
376         if (!_G.r0Pushed) {
377           //pic16_emitcode ("push","%s",
378           //          pic16_regWithIdx(R0_IDX)->dname);
379             _G.r0Pushed++ ;
380         }
381         
382         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
383         (*aopp)->type = AOP_R0;
384
385         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
386     }
387
388     /* if r1 not used then */
389
390     if (!r1iu) {
391         /* push it if not already pushed */
392         if (!_G.r1Pushed) {
393           //pic16_emitcode ("push","%s",
394           //          pic16_regWithIdx(R1_IDX)->dname);
395             _G.r1Pushed++ ;
396         }
397         
398         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
399         (*aopp)->type = AOP_R1;
400         return pic16_regWithIdx(R1_IDX);
401     }
402
403 endOfWorld :
404     /* I said end of world but not quite end of world yet */
405     /* if this is a result then we can push it on the stack*/
406     if (result) {
407         (*aopp)->type = AOP_STK;    
408         return NULL;
409     }
410
411     /* other wise this is true end of the world */
412     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
413            "getFreePtr should never reach here");
414     exit(0);
415 }
416
417 /*-----------------------------------------------------------------*/
418 /* newAsmop - creates a new asmOp                                  */
419 /*-----------------------------------------------------------------*/
420 static asmop *newAsmop (short type)
421 {
422     asmop *aop;
423
424     aop = Safe_calloc(1,sizeof(asmop));
425     aop->type = type;
426     return aop;
427 }
428
429 static void genSetDPTR(int n)
430 {
431     if (!n)
432     {
433         pic16_emitcode(";", "Select standard DPTR");
434         pic16_emitcode("mov", "dps, #0x00");
435     }
436     else
437     {
438         pic16_emitcode(";", "Select alternate DPTR");
439         pic16_emitcode("mov", "dps, #0x01");
440     }
441 }
442
443 /*-----------------------------------------------------------------*/
444 /* resolveIfx - converts an iCode ifx into a form more useful for  */
445 /*              generating code                                    */
446 /*-----------------------------------------------------------------*/
447 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
448 {
449   if(!resIfx) 
450     return;
451
452   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
453
454   resIfx->condition = 1;    /* assume that the ifx is true */
455   resIfx->generated = 0;    /* indicate that the ifx has not been used */
456
457   if(!ifx) {
458     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
459 /*
460     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
461                         __FUNCTION__,__LINE__,resIfx->lbl->key);
462 */
463   } else {
464     if(IC_TRUE(ifx)) {
465       resIfx->lbl = IC_TRUE(ifx);
466     } else {
467       resIfx->lbl = IC_FALSE(ifx);
468       resIfx->condition = 0;
469     }
470 /*
471     if(IC_TRUE(ifx)) 
472       DEBUGpic16_emitcode("; ***","ifx true is non-null");
473     if(IC_FALSE(ifx)) 
474       DEBUGpic16_emitcode("; ***","ifx false is non-null");
475 */
476   }
477
478   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
479
480 }
481 #if 0
482 /*-----------------------------------------------------------------*/
483 /* pointerCode - returns the code for a pointer type               */
484 /*-----------------------------------------------------------------*/
485 static int pointerCode (sym_link *etype)
486 {
487
488     return PTR_TYPE(SPEC_OCLS(etype));
489
490 }
491 #endif
492 /*-----------------------------------------------------------------*/
493 /* aopForSym - for a true symbol                                   */
494 /*-----------------------------------------------------------------*/
495 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
496 {
497     asmop *aop;
498     memmap *space= SPEC_OCLS(sym->etype);
499
500     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
501     /* if already has one */
502     if (sym->aop) {
503             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
504         return sym->aop;
505     }
506
507     /* assign depending on the storage class */
508     /* if it is on the stack or indirectly addressable */
509     /* space we need to assign either r0 or r1 to it   */    
510     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
511
512         DEBUGpic16_emitcode("; ***", "sum->onStack || sym->iaccess");
513         
514         sym->aop = aop = newAsmop(0);
515         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
516         aop->size = getSize(sym->type);
517
518         /* now assign the address of the variable to 
519         the pointer register */
520         if (aop->type != AOP_STK) {
521
522             if (sym->onStack) {
523                     if ( _G.accInUse )
524                         pic16_emitcode("push","acc");
525
526                     pic16_emitcode("mov","a,_bp");
527                     pic16_emitcode("add","a,#0x%02x",
528                              ((sym->stack < 0) ?
529                               ((char)(sym->stack - _G.nRegsSaved )) :
530                               ((char)sym->stack)) & 0xff);
531                     pic16_emitcode("mov","%s,a",
532                              aop->aopu.aop_ptr->name);
533
534                     if ( _G.accInUse )
535                         pic16_emitcode("pop","acc");
536             } else
537                 pic16_emitcode("mov","%s,#%s",
538                          aop->aopu.aop_ptr->name,
539                          sym->rname);
540             aop->paged = space->paged;
541         } else
542             aop->aopu.aop_stk = sym->stack;
543         return aop;
544     }
545     
546     if (sym->onStack && options.stack10bit)
547     {
548         /* It's on the 10 bit stack, which is located in
549          * far data space.
550          */
551          
552       //DEBUGpic16_emitcode(";","%d",__LINE__);
553
554         if ( _G.accInUse )
555                 pic16_emitcode("push","acc");
556
557         pic16_emitcode("mov","a,_bp");
558         pic16_emitcode("add","a,#0x%02x",
559                  ((sym->stack < 0) ?
560                    ((char)(sym->stack - _G.nRegsSaved )) :
561                    ((char)sym->stack)) & 0xff);
562         
563         genSetDPTR(1);
564         pic16_emitcode ("mov","dpx1,#0x40");
565         pic16_emitcode ("mov","dph1,#0x00");
566         pic16_emitcode ("mov","dpl1, a");
567         genSetDPTR(0);
568         
569         if ( _G.accInUse )
570             pic16_emitcode("pop","acc");
571             
572         sym->aop = aop = newAsmop(AOP_DPTR2);
573         aop->size = getSize(sym->type); 
574         return aop;
575     }
576
577     //DEBUGpic16_emitcode(";","%d",__LINE__);
578     /* if in bit space */
579     if (IN_BITSPACE(space)) {
580         sym->aop = aop = newAsmop (AOP_CRY);
581         aop->aopu.aop_dir = sym->rname ;
582         aop->size = getSize(sym->type);
583         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
584         return aop;
585     }
586     /* if it is in direct space */
587     if (IN_DIRSPACE(space)) {
588         sym->aop = aop = newAsmop (AOP_DIR);
589         aop->aopu.aop_dir = sym->rname ;
590         aop->size = getSize(sym->type);
591         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
592         pic16_allocDirReg( IC_LEFT(ic) );
593         return aop;
594     }
595
596 #if 0                                                                                           // patch 14
597     /* special case for a function */
598     if (IS_FUNC(sym->type)) {   
599         sym->aop = aop = newAsmop(AOP_IMMD);    
600         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
601         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
602         strcpy(aop->aopu.aop_immd,sym->rname);
603         aop->size = FPTRSIZE; 
604         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
605         return aop;
606     }
607 #endif                                                                                          // patch 14
608
609
610     /* only remaining is far space */
611     /* in which case DPTR gets the address */
612     sym->aop = aop = newAsmop(AOP_PCODE);
613
614 /* change the next if to 1 to revert to good old immediate code */
615         if(IN_CODESPACE(space)) {
616                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
617                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
618                 PCOI(aop->aopu.pcop)->index = 0;
619         } else {
620                 /* try to allocate via direct register */
621                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
622 //              aop->size = getSize( sym->type );
623         }
624
625         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
626                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
627
628 #if 0
629         if(!pic16_allocDirReg (IC_LEFT(ic)))
630                 return NULL;
631 #endif
632
633         if(IN_DIRSPACE( space ))
634                 aop->size = PTRSIZE;
635         else if(IN_CODESPACE( space ))
636                 aop->size = FPTRSIZE;
637         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
638         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
639         else {
640                 assert( 0 );
641         }
642
643     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
644
645     /* if it is in code space */
646     if (IN_CODESPACE(space))
647         aop->code = 1;
648
649     return aop;     
650 }
651
652 /*-----------------------------------------------------------------*/
653 /* aopForRemat - rematerialzes an object                           */
654 /*-----------------------------------------------------------------*/
655 static asmop *aopForRemat (operand *op) // x symbol *sym)
656 {
657   symbol *sym = OP_SYMBOL(op);
658   iCode *ic = NULL, *oldic;
659   asmop *aop = newAsmop(AOP_PCODE);
660   int val = 0;
661   int offset = 0;
662   int viaimmd=0;
663
664
665         ic = sym->rematiCode;
666
667         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
668         
669         if(IS_OP_POINTER(op)) {
670                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
671         }
672
673         for (;;) {
674                 oldic = ic;
675
676 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
677         
678                 if (ic->op == '+') {
679                         val += (int) operandLitValue(IC_RIGHT(ic));
680                 } else if (ic->op == '-') {
681                         val -= (int) operandLitValue(IC_RIGHT(ic));
682                 } else
683                         break;
684                 
685                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
686         }
687
688         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
689
690         if(!op->isaddr)viaimmd++; else viaimmd=0;
691                 
692 /* set the following if to 1 to revert to good old immediate code */
693         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
694                 || viaimmd) {
695
696                 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
697
698                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
699
700 #if 0
701                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
702 #else
703                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
704 #endif
705
706                 PCOI(aop->aopu.pcop)->index = val;
707         } else {
708                 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
709
710                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
711 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
712         }
713
714
715         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
716                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
717 #if 0
718                 val, IS_PTR_CONST(operandType(op)));
719 #else
720                 val, IS_CODEPTR(operandType(op)));
721 #endif
722
723 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
724
725         pic16_allocDirReg (IC_LEFT(ic));
726
727         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
728                 aop->code = 1;
729
730   return aop;        
731 }
732
733 static int aopIdx (asmop *aop, int offset)
734 {
735   if(!aop)
736     return -1;
737
738   if(aop->type !=  AOP_REG)
739     return -2;
740         
741   return aop->aopu.aop_reg[offset]->rIdx;
742
743 }
744 /*-----------------------------------------------------------------*/
745 /* regsInCommon - two operands have some registers in common       */
746 /*-----------------------------------------------------------------*/
747 static bool regsInCommon (operand *op1, operand *op2)
748 {
749     symbol *sym1, *sym2;
750     int i;
751
752     /* if they have registers in common */
753     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
754         return FALSE ;
755
756     sym1 = OP_SYMBOL(op1);
757     sym2 = OP_SYMBOL(op2);
758
759     if (sym1->nRegs == 0 || sym2->nRegs == 0)
760         return FALSE ;
761
762     for (i = 0 ; i < sym1->nRegs ; i++) {
763         int j;
764         if (!sym1->regs[i])
765             continue ;
766
767         for (j = 0 ; j < sym2->nRegs ;j++ ) {
768             if (!sym2->regs[j])
769                 continue ;
770
771             if (sym2->regs[j] == sym1->regs[i])
772                 return TRUE ;
773         }
774     }
775
776     return FALSE ;
777 }
778
779 /*-----------------------------------------------------------------*/
780 /* operandsEqu - equivalent                                        */
781 /*-----------------------------------------------------------------*/
782 static bool operandsEqu ( operand *op1, operand *op2)
783 {
784     symbol *sym1, *sym2;
785
786     /* if they not symbols */
787     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
788         return FALSE;
789
790     sym1 = OP_SYMBOL(op1);
791     sym2 = OP_SYMBOL(op2);
792
793     /* if both are itemps & one is spilt
794        and the other is not then false */
795     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
796         sym1->isspilt != sym2->isspilt )
797         return FALSE ;
798
799     /* if they are the same */
800     if (sym1 == sym2)
801         return TRUE ;
802
803     if (strcmp(sym1->rname,sym2->rname) == 0)
804         return TRUE;
805
806
807     /* if left is a tmp & right is not */
808     if (IS_ITEMP(op1)  && 
809         !IS_ITEMP(op2) &&
810         sym1->isspilt  &&
811         (sym1->usl.spillLoc == sym2))
812         return TRUE;
813
814     if (IS_ITEMP(op2)  && 
815         !IS_ITEMP(op1) &&
816         sym2->isspilt  &&
817         sym1->level > 0 &&
818         (sym2->usl.spillLoc == sym1))
819         return TRUE ;
820
821     return FALSE ;
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* pic16_sameRegs - two asmops have the same registers                   */
826 /*-----------------------------------------------------------------*/
827 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
828 {
829     int i;
830
831     if (aop1 == aop2)
832         return TRUE ;
833
834     if (aop1->type != AOP_REG ||
835         aop2->type != AOP_REG )
836         return FALSE ;
837
838     if (aop1->size != aop2->size )
839         return FALSE ;
840
841     for (i = 0 ; i < aop1->size ; i++ )
842         if (aop1->aopu.aop_reg[i] !=
843             aop2->aopu.aop_reg[i] )
844             return FALSE ;
845
846     return TRUE ;
847 }
848
849 /*-----------------------------------------------------------------*/
850 /* pic16_aopOp - allocates an asmop for an operand  :                    */
851 /*-----------------------------------------------------------------*/
852 void pic16_aopOp (operand *op, iCode *ic, bool result)
853 {
854     asmop *aop;
855     symbol *sym;
856     int i;
857
858     if (!op)
859         return ;
860
861 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
862
863     /* if this a literal */
864     if (IS_OP_LITERAL(op)) {
865         op->aop = aop = newAsmop(AOP_LIT);
866         aop->aopu.aop_lit = op->operand.valOperand;
867         aop->size = getSize(operandType(op));
868         return;
869     }
870
871     {
872       sym_link *type = operandType(op);
873 #if 0
874       if(IS_PTR_CONST(type))
875 #else
876       if(IS_CODEPTR(type))
877 #endif
878         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
879     }
880
881     /* if already has a asmop then continue */
882     if (op->aop)
883         return ;
884
885     /* if the underlying symbol has a aop */
886     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
887       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
888         op->aop = OP_SYMBOL(op)->aop;
889         return;
890     }
891
892     /* if this is a true symbol */
893     if (IS_TRUE_SYMOP(op)) {    
894         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
895       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
896       return ;
897     }
898
899     /* this is a temporary : this has
900     only four choices :
901     a) register
902     b) spillocation
903     c) rematerialize 
904     d) conditional   
905     e) can be a return use only */
906
907     sym = OP_SYMBOL(op);
908
909         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
910     /* if the type is a conditional */
911     if (sym->regType == REG_CND) {
912         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
913         aop->size = 0;
914         return;
915     }
916
917     /* if it is spilt then two situations
918     a) is rematerialize 
919     b) has a spill location */
920     if (sym->isspilt || sym->nRegs == 0) {
921
922       DEBUGpic16_emitcode(";","%d",__LINE__);
923         /* rematerialize it NOW */
924         if (sym->remat) {
925
926             sym->aop = op->aop = aop =
927                                       aopForRemat (op);
928             aop->size = getSize(sym->type);
929             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
930             return;
931         }
932
933 #if 1
934         if (sym->accuse) {
935             int i;
936             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
937             aop->size = getSize(sym->type);
938             for ( i = 0 ; i < 1 ; i++ ) {
939                 aop->aopu.aop_str[i] = accUse[i];
940 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
941             }
942             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
943             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
944             return;  
945         }
946 #endif
947
948 #if 1
949         if (sym->ruonly ) {
950           /*
951           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
952           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
953           //pic16_allocDirReg (IC_LEFT(ic));
954           aop->size = getSize(sym->type);
955           */
956
957           unsigned i;
958
959           aop = op->aop = sym->aop = newAsmop(AOP_STR);
960           aop->size = getSize(sym->type);
961           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
962             aop->aopu.aop_str[i] = fReturn[i];
963
964           DEBUGpic16_emitcode(";","%d",__LINE__);
965           return;
966         }
967 #endif
968         /* else spill location  */
969         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
970             /* force a new aop if sizes differ */
971             sym->usl.spillLoc->aop = NULL;
972         }
973         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
974                             __FUNCTION__,__LINE__,
975                             sym->usl.spillLoc->rname,
976                             sym->rname, sym->usl.spillLoc->offset);
977
978         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
979         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
980         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
981                                           getSize(sym->type), 
982                                           sym->usl.spillLoc->offset);
983         aop->size = getSize(sym->type);
984
985         return;
986     }
987
988     {
989       sym_link *type = operandType(op);
990 #if 0
991       if(IS_PTR_CONST(type)) 
992 #else
993       if(IS_CODEPTR(type)) 
994 #endif
995         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
996     }
997
998     /* must be in a register */
999     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1000     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1001     aop->size = sym->nRegs;
1002     for ( i = 0 ; i < sym->nRegs ;i++)
1003         aop->aopu.aop_reg[i] = sym->regs[i];
1004 }
1005
1006 /*-----------------------------------------------------------------*/
1007 /* pic16_freeAsmop - free up the asmop given to an operand               */
1008 /*----------------------------------------------------------------*/
1009 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1010 {   
1011     asmop *aop ;
1012
1013     if (!op)
1014         aop = aaop;
1015     else 
1016         aop = op->aop;
1017
1018     if (!aop)
1019         return ;
1020
1021     if (aop->freed)
1022         goto dealloc; 
1023
1024     aop->freed = 1;
1025
1026     /* depending on the asmop type only three cases need work AOP_RO
1027        , AOP_R1 && AOP_STK */
1028 #if 0
1029     switch (aop->type) {
1030         case AOP_R0 :
1031             if (_G.r0Pushed ) {
1032                 if (pop) {
1033                     pic16_emitcode ("pop","ar0");     
1034                     _G.r0Pushed--;
1035                 }
1036             }
1037             bitVectUnSetBit(ic->rUsed,R0_IDX);
1038             break;
1039
1040         case AOP_R1 :
1041             if (_G.r1Pushed ) {
1042                 if (pop) {
1043                     pic16_emitcode ("pop","ar1");
1044                     _G.r1Pushed--;
1045                 }
1046             }
1047             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1048             break;
1049
1050         case AOP_STK :
1051         {
1052             int sz = aop->size;    
1053             int stk = aop->aopu.aop_stk + aop->size;
1054             bitVectUnSetBit(ic->rUsed,R0_IDX);
1055             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1056
1057             getFreePtr(ic,&aop,FALSE);
1058             
1059             if (options.stack10bit)
1060             {
1061                 /* I'm not sure what to do here yet... */
1062                 /* #STUB */
1063                 fprintf(stderr, 
1064                         "*** Warning: probably generating bad code for "
1065                         "10 bit stack mode.\n");
1066             }
1067             
1068             if (stk) {
1069                 pic16_emitcode ("mov","a,_bp");
1070                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1071                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1072             } else {
1073                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1074             }
1075
1076             while (sz--) {
1077                 pic16_emitcode("pop","acc");
1078                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1079                 if (!sz) break;
1080                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1081             }
1082             op->aop = aop;
1083             pic16_freeAsmop(op,NULL,ic,TRUE);
1084             if (_G.r0Pushed) {
1085                 pic16_emitcode("pop","ar0");
1086                 _G.r0Pushed--;
1087             }
1088
1089             if (_G.r1Pushed) {
1090                 pic16_emitcode("pop","ar1");
1091                 _G.r1Pushed--;
1092             }       
1093         }
1094     }
1095 #endif
1096
1097 dealloc:
1098     /* all other cases just dealloc */
1099     if (op ) {
1100         op->aop = NULL;
1101         if (IS_SYMOP(op)) {
1102             OP_SYMBOL(op)->aop = NULL;    
1103             /* if the symbol has a spill */
1104             if (SPIL_LOC(op))
1105                 SPIL_LOC(op)->aop = NULL;
1106         }
1107     }
1108 }
1109
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_aopGet - for fetching value of the aop                          */
1112 /*-----------------------------------------------------------------*/
1113 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1114 {
1115     char *s = buffer ;
1116     char *rs;
1117
1118     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1119
1120     /* offset is greater than size then zero */
1121     if (offset > (aop->size - 1) &&
1122         aop->type != AOP_LIT)
1123         return zero;
1124
1125     /* depending on type */
1126     switch (aop->type) {
1127         
1128     case AOP_R0:
1129     case AOP_R1:
1130         DEBUGpic16_emitcode(";","%d",__LINE__);
1131         /* if we need to increment it */       
1132         while (offset > aop->coff) {        
1133             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1134             aop->coff++;
1135         }
1136         
1137         while (offset < aop->coff) {
1138             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1139             aop->coff--;
1140         }
1141         
1142         aop->coff = offset ;
1143         if (aop->paged) {
1144             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1145             return (dname ? "acc" : "a");
1146         }       
1147         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1148         rs = Safe_calloc(1,strlen(s)+1);
1149         strcpy(rs,s);   
1150         return rs;
1151         
1152     case AOP_DPTR:
1153     case AOP_DPTR2:
1154         DEBUGpic16_emitcode(";","%d",__LINE__);
1155     if (aop->type == AOP_DPTR2)
1156     {
1157         genSetDPTR(1);
1158     }
1159     
1160         while (offset > aop->coff) {
1161             pic16_emitcode ("inc","dptr");
1162             aop->coff++;
1163         }
1164         
1165         while (offset < aop->coff) {        
1166             pic16_emitcode("lcall","__decdptr");
1167             aop->coff--;
1168         }
1169         
1170         aop->coff = offset;
1171         if (aop->code) {
1172             pic16_emitcode("clr","a");
1173             pic16_emitcode("movc","a,@a+dptr");
1174         }
1175     else {
1176             pic16_emitcode("movx","a,@dptr");
1177     }
1178             
1179     if (aop->type == AOP_DPTR2)
1180     {
1181         genSetDPTR(0);
1182     }
1183             
1184     return (dname ? "acc" : "a");
1185         
1186         
1187     case AOP_IMMD:
1188         if (bit16) 
1189             sprintf (s,"%s",aop->aopu.aop_immd);
1190         else
1191             if (offset) 
1192                 sprintf(s,"(%s >> %d)",
1193                         aop->aopu.aop_immd,
1194                         offset*8);
1195             else
1196                 sprintf(s,"%s",
1197                         aop->aopu.aop_immd);
1198         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1199         rs = Safe_calloc(1,strlen(s)+1);
1200         strcpy(rs,s);   
1201         return rs;
1202         
1203     case AOP_DIR:
1204       if (offset) {
1205         sprintf(s,"(%s + %d)",
1206                 aop->aopu.aop_dir,
1207                 offset);
1208         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1209       } else
1210             sprintf(s,"%s",aop->aopu.aop_dir);
1211         rs = Safe_calloc(1,strlen(s)+1);
1212         strcpy(rs,s);   
1213         return rs;
1214         
1215     case AOP_REG:
1216       //if (dname) 
1217       //    return aop->aopu.aop_reg[offset]->dname;
1218       //else
1219             return aop->aopu.aop_reg[offset]->name;
1220         
1221     case AOP_CRY:
1222       //pic16_emitcode(";","%d",__LINE__);
1223       return aop->aopu.aop_dir;
1224         
1225     case AOP_ACC:
1226         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1227 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1228 //        assert( 0 );
1229         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1230
1231     case AOP_LIT:
1232         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1233         rs = Safe_calloc(1,strlen(s)+1);
1234         strcpy(rs,s);   
1235         return rs;
1236         
1237     case AOP_STR:
1238         aop->coff = offset ;
1239         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1240             dname)
1241             return "acc";
1242         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1243         
1244         return aop->aopu.aop_str[offset];
1245         
1246     case AOP_PCODE:
1247       {
1248         pCodeOp *pcop = aop->aopu.pcop;
1249         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1250         if(pcop->name) {
1251           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1252           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1253           sprintf(s,"%s", pcop->name);
1254         } else
1255           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1256
1257       }
1258       rs = Safe_calloc(1,strlen(s)+1);
1259       strcpy(rs,s);   
1260       return rs;
1261
1262     }
1263
1264     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1265            "aopget got unsupported aop->type");
1266     exit(0);
1267 }
1268
1269
1270 /*-----------------------------------------------------------------*/
1271 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1272 /*-----------------------------------------------------------------*/
1273 pCodeOp *pic16_popGetTempReg(void)
1274 {
1275   pCodeOp *pcop;
1276
1277         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1278         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1279                 PCOR(pcop)->r->wasUsed=1;
1280                 PCOR(pcop)->r->isFree=0;
1281
1282                 /* push value on stack */
1283                 pic16_pushpCodeOp( pcop );
1284         }
1285
1286   return pcop;
1287 }
1288
1289 /*-----------------------------------------------------------------*/
1290 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1291 /*-----------------------------------------------------------------*/
1292 void pic16_popReleaseTempReg(pCodeOp *pcop)
1293 {
1294         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1295                 PCOR(pcop)->r->isFree = 1;
1296                 
1297                 pic16_poppCodeOp( pcop );
1298         }
1299 }
1300 /*-----------------------------------------------------------------*/
1301 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1302 /*-----------------------------------------------------------------*/
1303 pCodeOp *pic16_popGetLabel(unsigned int key)
1304 {
1305
1306   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1307
1308   if(key>max_key)
1309     max_key = key;
1310
1311   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1312 }
1313
1314 /*-----------------------------------------------------------------*/
1315 /* pic16_popCopyReg - copy a pcode operator                              */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1318 {
1319   pCodeOpReg *pcor;
1320
1321   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1322   pcor->pcop.type = pc->pcop.type;
1323   if(pc->pcop.name) {
1324     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1325       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1326   } else
1327     pcor->pcop.name = NULL;
1328
1329   pcor->r = pc->r;
1330   pcor->rIdx = pc->rIdx;
1331   pcor->r->wasUsed=1;
1332
1333 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1334
1335   return PCOP(pcor);
1336 }
1337
1338 /*-----------------------------------------------------------------*/
1339 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1340 /*-----------------------------------------------------------------*/
1341 pCodeOp *pic16_popGetLit(unsigned int lit)
1342 {
1343   return pic16_newpCodeOpLit(lit);
1344 }
1345
1346 /*-----------------------------------------------------------------*/
1347 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1348 /*-----------------------------------------------------------------*/
1349 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1350 {
1351   return pic16_newpCodeOpLit2(lit, arg2);
1352 }
1353
1354
1355 /*-----------------------------------------------------------------*/
1356 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1357 /*-----------------------------------------------------------------*/
1358 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1359 {
1360   return pic16_newpCodeOpImmd(name, offset,index, 0);
1361 }
1362
1363
1364 /*-----------------------------------------------------------------*/
1365 /* pic16_popGet - asm operator to pcode operator conversion              */
1366 /*-----------------------------------------------------------------*/
1367 pCodeOp *pic16_popGetWithString(char *str)
1368 {
1369   pCodeOp *pcop;
1370
1371
1372   if(!str) {
1373     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1374     exit (1);
1375   }
1376
1377   pcop = pic16_newpCodeOp(str,PO_STR);
1378
1379   return pcop;
1380 }
1381
1382 /*-----------------------------------------------------------------*/
1383 /* pic16_popRegFromString -                                        */
1384 /*-----------------------------------------------------------------*/
1385 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1386 {
1387
1388   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1389   pcop->type = PO_DIR;
1390
1391   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1392   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1393
1394   if(!str)
1395     str = "BAD_STRING";
1396
1397   pcop->name = Safe_calloc(1,strlen(str)+1);
1398   strcpy(pcop->name,str);
1399
1400   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1401
1402   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1403   if(PCOR(pcop)->r == NULL) {
1404 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1405 //              __FUNCTION__, __LINE__, str, size, offset);
1406     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1407
1408         //fprintf(stderr, "allocating new register -> %s\n", str);
1409
1410 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1411   } else {
1412 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1413   }
1414   PCOR(pcop)->instance = offset;
1415
1416   return pcop;
1417 }
1418
1419 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1420 {
1421   pCodeOp *pcop;
1422
1423 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1424
1425         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1426         PCOR(pcop)->rIdx = rIdx;
1427         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1428         PCOR(pcop)->r->isFree = 0;
1429         PCOR(pcop)->r->wasUsed = 1;
1430
1431         pcop->type = PCOR(pcop)->r->pc_type;
1432
1433   return pcop;
1434 }
1435
1436 /*---------------------------------------------------------------------------------*/
1437 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1438 /*                 VR 030601                                                       */
1439 /*---------------------------------------------------------------------------------*/
1440 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1441 {
1442   pCodeOpReg2 *pcop2;
1443   pCodeOp *temp;
1444   
1445         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1446
1447         /* comment the following check, so errors to throw up */
1448 //      if(!pcop2)return NULL;
1449
1450         temp = pic16_popGet(aop_dst, offset);
1451         pcop2->pcop2 = temp;
1452         
1453   return PCOP(pcop2);
1454 }
1455
1456
1457
1458 /*--------------------------------------------------------------------------------.-*/
1459 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1460 /*                  VR 030601 , adapted by Hans Dorn                                */
1461 /*--------------------------------------------------------------------------------.-*/
1462 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1463 {
1464   pCodeOpReg2 *pcop2;
1465  
1466         pcop2 = (pCodeOpReg2 *)src;
1467         pcop2->pcop2 = dst;
1468         
1469         return PCOP(pcop2);
1470 }
1471
1472
1473
1474 /*---------------------------------------------------------------------------------*/
1475 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1476 /*                     movff instruction                                           */
1477 /*---------------------------------------------------------------------------------*/
1478 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1479 {
1480   pCodeOpReg2 *pcop2;
1481
1482         if(!noalloc) {
1483                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1484                 pcop2->pcop2 = pic16_popCopyReg(dst);
1485         } else {
1486                 /* the pCodeOp may be already allocated */
1487                 pcop2 = (pCodeOpReg2 *)(src);
1488                 pcop2->pcop2 = (pCodeOp *)(dst);
1489         }
1490
1491   return PCOP(pcop2);
1492 }
1493
1494
1495 /*-----------------------------------------------------------------*/
1496 /* pic16_popGet - asm operator to pcode operator conversion              */
1497 /*-----------------------------------------------------------------*/
1498 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1499 {
1500   //char *s = buffer ;
1501   char *rs;
1502   pCodeOp *pcop;
1503
1504     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1505     /* offset is greater than
1506     size then zero */
1507
1508 //    if (offset > (aop->size - 1) &&
1509 //        aop->type != AOP_LIT)
1510 //      return NULL;  //zero;
1511
1512     /* depending on type */
1513     switch (aop->type) {
1514         
1515     case AOP_R0:
1516     case AOP_R1:
1517     case AOP_DPTR:
1518     case AOP_DPTR2:
1519         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1520         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1521         assert( 0 );
1522         return NULL;
1523
1524
1525
1526     case AOP_IMMD:
1527       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1528       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1529
1530     case AOP_ACC:
1531       {
1532         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1533
1534         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1535
1536         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1537         
1538         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1539         PCOR(pcop)->rIdx = rIdx;
1540         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1541         PCOR(pcop)->r->wasUsed=1;
1542         PCOR(pcop)->r->isFree=0;
1543
1544         PCOR(pcop)->instance = offset;
1545         pcop->type = PCOR(pcop)->r->pc_type;
1546 //      rs = aop->aopu.aop_reg[offset]->name;
1547 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1548         return pcop;
1549
1550
1551 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1552 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1553
1554 //      assert( 0 );
1555       }
1556         
1557     case AOP_DIR:
1558       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1559       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1560         
1561     case AOP_REG:
1562       {
1563         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1564
1565         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1566         
1567         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1568         PCOR(pcop)->rIdx = rIdx;
1569         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1570         PCOR(pcop)->r->wasUsed=1;
1571         PCOR(pcop)->r->isFree=0;
1572
1573         PCOR(pcop)->instance = offset;
1574         pcop->type = PCOR(pcop)->r->pc_type;
1575         rs = aop->aopu.aop_reg[offset]->name;
1576         DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1577         return pcop;
1578       }
1579
1580     case AOP_CRY:
1581         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1582
1583       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1584       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1585       //if(PCOR(pcop)->r == NULL)
1586       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1587       return pcop;
1588         
1589     case AOP_LIT:
1590         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1591       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1592
1593     case AOP_STR:
1594       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1595       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1596
1597       /*
1598       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1600       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1601       pcop->type = PCOR(pcop)->r->pc_type;
1602       pcop->name = PCOR(pcop)->r->name;
1603
1604       return pcop;
1605       */
1606
1607     case AOP_PCODE:
1608       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1609                           __LINE__, 
1610                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1611       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1612 #if 1
1613         switch( aop->aopu.pcop->type ) {
1614                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1615                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1616                 default:
1617                         assert( 0 );    /* should never reach here */;
1618         }
1619 #else
1620       PCOI(pcop)->offset = offset;
1621 #endif
1622       return pcop;
1623     }
1624
1625     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626            "pic16_popGet got unsupported aop->type");
1627     exit(0);
1628 }
1629 /*-----------------------------------------------------------------*/
1630 /* pic16_aopPut - puts a string for a aop                                */
1631 /*-----------------------------------------------------------------*/
1632 void pic16_aopPut (asmop *aop, char *s, int offset)
1633 {
1634     char *d = buffer ;
1635     symbol *lbl ;
1636
1637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1638
1639     if (aop->size && offset > ( aop->size - 1)) {
1640         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1641                "pic16_aopPut got offset > aop->size");
1642         exit(0);
1643     }
1644
1645     /* will assign value to value */
1646     /* depending on where it is ofcourse */
1647     switch (aop->type) {
1648     case AOP_DIR:
1649       if (offset) {
1650         sprintf(d,"(%s + %d)",
1651                 aop->aopu.aop_dir,offset);
1652         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1653
1654       } else
1655             sprintf(d,"%s",aop->aopu.aop_dir);
1656         
1657         if (strcmp(d,s)) {
1658           DEBUGpic16_emitcode(";","%d",__LINE__);
1659           if(strcmp(s,"W"))
1660             pic16_emitcode("movf","%s,w",s);
1661           pic16_emitcode("movwf","%s",d);
1662
1663           if(strcmp(s,"W")) {
1664             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1665             if(offset >= aop->size) {
1666               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1667               break;
1668             } else
1669               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1670           }
1671
1672           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1673
1674
1675         }
1676         break;
1677         
1678     case AOP_REG:
1679       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1680         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1681           /*
1682             if (*s == '@'           ||
1683                 strcmp(s,"r0") == 0 ||
1684                 strcmp(s,"r1") == 0 ||
1685                 strcmp(s,"r2") == 0 ||
1686                 strcmp(s,"r3") == 0 ||
1687                 strcmp(s,"r4") == 0 ||
1688                 strcmp(s,"r5") == 0 ||
1689                 strcmp(s,"r6") == 0 || 
1690                 strcmp(s,"r7") == 0 )
1691                 pic16_emitcode("mov","%s,%s  ; %d",
1692                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1693             else
1694           */
1695
1696           if(strcmp(s,"W")==0 )
1697             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1698
1699           pic16_emitcode("movwf","%s",
1700                    aop->aopu.aop_reg[offset]->name);
1701
1702           if(strcmp(s,zero)==0) {
1703             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1704
1705           } else if(strcmp(s,"W")==0) {
1706             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1707             pcop->type = PO_GPR_REGISTER;
1708
1709             PCOR(pcop)->rIdx = -1;
1710             PCOR(pcop)->r = NULL;
1711
1712             DEBUGpic16_emitcode(";","%d",__LINE__);
1713             pcop->name = Safe_strdup(s);
1714             pic16_emitpcode(POC_MOVFW,pcop);
1715             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1716           } else if(strcmp(s,one)==0) {
1717             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1718             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1719           } else {
1720             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1721           }
1722         }
1723         break;
1724         
1725     case AOP_DPTR:
1726     case AOP_DPTR2:
1727     
1728     if (aop->type == AOP_DPTR2)
1729     {
1730         genSetDPTR(1);
1731     }
1732     
1733         if (aop->code) {
1734             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1735                    "pic16_aopPut writting to code space");
1736             exit(0);
1737         }
1738         
1739         while (offset > aop->coff) {
1740             aop->coff++;
1741             pic16_emitcode ("inc","dptr");
1742         }
1743         
1744         while (offset < aop->coff) {
1745             aop->coff-- ;
1746             pic16_emitcode("lcall","__decdptr");
1747         }
1748         
1749         aop->coff = offset;
1750         
1751         /* if not in accumulater */
1752         MOVA(s);        
1753         
1754         pic16_emitcode ("movx","@dptr,a");
1755         
1756     if (aop->type == AOP_DPTR2)
1757     {
1758         genSetDPTR(0);
1759     }
1760         break;
1761         
1762     case AOP_R0:
1763     case AOP_R1:
1764         while (offset > aop->coff) {
1765             aop->coff++;
1766             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1767         }
1768         while (offset < aop->coff) {
1769             aop->coff-- ;
1770             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1771         }
1772         aop->coff = offset;
1773         
1774         if (aop->paged) {
1775             MOVA(s);           
1776             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1777             
1778         } else
1779             if (*s == '@') {
1780                 MOVA(s);
1781                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1782             } else
1783                 if (strcmp(s,"r0") == 0 ||
1784                     strcmp(s,"r1") == 0 ||
1785                     strcmp(s,"r2") == 0 ||
1786                     strcmp(s,"r3") == 0 ||
1787                     strcmp(s,"r4") == 0 ||
1788                     strcmp(s,"r5") == 0 ||
1789                     strcmp(s,"r6") == 0 || 
1790                     strcmp(s,"r7") == 0 ) {
1791                     char buffer[10];
1792                     sprintf(buffer,"a%s",s);
1793                     pic16_emitcode("mov","@%s,%s",
1794                              aop->aopu.aop_ptr->name,buffer);
1795                 } else
1796                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1797         
1798         break;
1799         
1800     case AOP_STK:
1801         if (strcmp(s,"a") == 0)
1802             pic16_emitcode("push","acc");
1803         else
1804             pic16_emitcode("push","%s",s);
1805         
1806         break;
1807         
1808     case AOP_CRY:
1809         /* if bit variable */
1810         if (!aop->aopu.aop_dir) {
1811             pic16_emitcode("clr","a");
1812             pic16_emitcode("rlc","a");
1813         } else {
1814             if (s == zero) 
1815                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1816             else
1817                 if (s == one)
1818                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1819                 else
1820                     if (!strcmp(s,"c"))
1821                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1822                     else {
1823                         lbl = newiTempLabel(NULL);
1824                         
1825                         if (strcmp(s,"a")) {
1826                             MOVA(s);
1827                         }
1828                         pic16_emitcode("clr","c");
1829                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1830                         pic16_emitcode("cpl","c");
1831                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1832                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1833                     }
1834         }
1835         break;
1836         
1837     case AOP_STR:
1838         aop->coff = offset;
1839         if (strcmp(aop->aopu.aop_str[offset],s))
1840             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1841         break;
1842         
1843     case AOP_ACC:
1844         aop->coff = offset;
1845         if (!offset && (strcmp(s,"acc") == 0))
1846             break;
1847         
1848         if (strcmp(aop->aopu.aop_str[offset],s))
1849             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1850         break;
1851
1852     default :
1853         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1854                "pic16_aopPut got unsupported aop->type");
1855         exit(0);    
1856     }    
1857
1858 }
1859
1860 /*-----------------------------------------------------------------*/
1861 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1862 /*-----------------------------------------------------------------*/
1863 static void mov2w (asmop *aop, int offset)
1864 {
1865
1866   if(!aop)
1867     return;
1868
1869   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1870
1871   if ( aop->type == AOP_PCODE ||
1872        aop->type == AOP_LIT )
1873     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1874   else
1875     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1876
1877 }
1878
1879
1880 /* push pcop into stack */
1881 void pic16_pushpCodeOp(pCodeOp *pcop)
1882 {
1883         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1884 }
1885
1886 /* pop pcop from stack */
1887 void pic16_poppCodeOp(pCodeOp *pcop)
1888 {
1889         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1890 }
1891
1892
1893 /*-----------------------------------------------------------------*/
1894 /* pushw - pushes wreg to stack                                    */
1895 /*-----------------------------------------------------------------*/
1896 void pushw(void)
1897 {
1898         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1899         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1900 }
1901
1902                 
1903 /*-----------------------------------------------------------------*/
1904 /* pushaop - pushes aop to stack                                   */
1905 /*-----------------------------------------------------------------*/
1906 void pushaop(asmop *aop, int offset)
1907 {
1908         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1910 }
1911
1912 /*-----------------------------------------------------------------*/
1913 /* popaop - pops aop from stack                                    */
1914 /*-----------------------------------------------------------------*/
1915 void popaop(asmop *aop, int offset)
1916 {
1917         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1918         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1919 }
1920
1921 void popaopidx(asmop *aop, int offset, int index)
1922 {
1923   int ofs=1;
1924
1925         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1926
1927         if(STACK_MODEL_LARGE)ofs++;
1928
1929         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1930         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1931 }
1932
1933 /*-----------------------------------------------------------------*/
1934 /* reAdjustPreg - points a register back to where it should        */
1935 /*-----------------------------------------------------------------*/
1936 static void reAdjustPreg (asmop *aop)
1937 {
1938     int size ;
1939
1940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1941     aop->coff = 0;
1942     if ((size = aop->size) <= 1)
1943         return ;
1944     size-- ;
1945     switch (aop->type) {
1946         case AOP_R0 :
1947         case AOP_R1 :
1948             while (size--)
1949                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1950             break;          
1951         case AOP_DPTR :
1952         case AOP_DPTR2:
1953             if (aop->type == AOP_DPTR2)
1954             {
1955                 genSetDPTR(1);
1956             } 
1957             while (size--)
1958             {
1959                 pic16_emitcode("lcall","__decdptr");
1960             }
1961                 
1962             if (aop->type == AOP_DPTR2)
1963             {
1964                 genSetDPTR(0);
1965             }                
1966             break;  
1967
1968     }   
1969
1970 }
1971
1972
1973 #if 0
1974 /*-----------------------------------------------------------------*/
1975 /* opIsGptr: returns non-zero if the passed operand is             */   
1976 /* a generic pointer type.                                         */
1977 /*-----------------------------------------------------------------*/ 
1978 static int opIsGptr(operand *op)
1979 {
1980     sym_link *type = operandType(op);
1981     
1982     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1983     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1984     {
1985         return 1;
1986     }
1987     return 0;        
1988 }
1989 #endif
1990
1991 /*-----------------------------------------------------------------*/
1992 /* pic16_getDataSize - get the operand data size                         */
1993 /*-----------------------------------------------------------------*/
1994 int pic16_getDataSize(operand *op)
1995 {
1996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1997
1998
1999     return AOP_SIZE(op);
2000
2001     // tsd- in the pic port, the genptr size is 1, so this code here
2002     // fails. ( in the 8051 port, the size was 4).
2003 #if 0
2004     int size;
2005     size = AOP_SIZE(op);
2006     if (size == GPTRSIZE)
2007     {
2008         sym_link *type = operandType(op);
2009         if (IS_GENPTR(type))
2010         {
2011             /* generic pointer; arithmetic operations
2012              * should ignore the high byte (pointer type).
2013              */
2014             size--;
2015     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2016         }
2017     }
2018     return size;
2019 #endif
2020 }
2021
2022 /*-----------------------------------------------------------------*/
2023 /* pic16_outAcc - output Acc                                             */
2024 /*-----------------------------------------------------------------*/
2025 void pic16_outAcc(operand *result)
2026 {
2027   int size,offset;
2028   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2029   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2030
2031
2032   size = pic16_getDataSize(result);
2033   if(size){
2034     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2035     size--;
2036     offset = 1;
2037     /* unsigned or positive */
2038     while(size--)
2039       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2040   }
2041
2042 }
2043
2044 /*-----------------------------------------------------------------*/
2045 /* pic16_outBitC - output a bit C                                        */
2046 /*-----------------------------------------------------------------*/
2047 void pic16_outBitC(operand *result)
2048 {
2049
2050     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2051     /* if the result is bit */
2052     if (AOP_TYPE(result) == AOP_CRY) 
2053         pic16_aopPut(AOP(result),"c",0);
2054     else {
2055         pic16_emitcode("clr","a  ; %d", __LINE__);
2056         pic16_emitcode("rlc","a");
2057         pic16_outAcc(result);
2058     }
2059 }
2060
2061 /*-----------------------------------------------------------------*/
2062 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2063 /*-----------------------------------------------------------------*/
2064 void pic16_toBoolean(operand *oper)
2065 {
2066     int size = AOP_SIZE(oper) - 1;
2067     int offset = 1;
2068
2069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2070
2071     if ( AOP_TYPE(oper) != AOP_ACC) {
2072       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2073     }
2074     while (size--) {
2075       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2076     }
2077 }
2078
2079
2080 #if !defined(GEN_Not)
2081 /*-----------------------------------------------------------------*/
2082 /* genNot - generate code for ! operation                          */
2083 /*-----------------------------------------------------------------*/
2084 static void pic16_genNot (iCode *ic)
2085 {
2086   symbol *tlbl;
2087   int size;
2088
2089   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090   /* assign asmOps to operand & result */
2091   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2092   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2093
2094   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2095   /* if in bit space then a special case */
2096   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2097     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2098       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2099       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2100     } else {
2101       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2102       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2103       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2104     }
2105     goto release;
2106   }
2107
2108   size = AOP_SIZE(IC_LEFT(ic));
2109   if(size == 1) {
2110     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2111     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2112     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2113     goto release;
2114   }
2115   pic16_toBoolean(IC_LEFT(ic));
2116
2117   tlbl = newiTempLabel(NULL);
2118   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2119   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2120   pic16_outBitC(IC_RESULT(ic));
2121
2122  release:    
2123   /* release the aops */
2124   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2125   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2126 }
2127 #endif
2128
2129
2130 #if !defined(GEN_Cpl)
2131 /*-----------------------------------------------------------------*/
2132 /* genCpl - generate code for complement                           */
2133 /*-----------------------------------------------------------------*/
2134 static void pic16_genCpl (iCode *ic)
2135 {
2136     int offset = 0;
2137     int size ;
2138
2139
2140     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2141     /* assign asmOps to operand & result */
2142     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2143     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2144
2145     /* if both are in bit space then 
2146     a special case */
2147     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2148         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2149
2150         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2151         pic16_emitcode("cpl","c"); 
2152         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2153         goto release; 
2154     } 
2155
2156     size = AOP_SIZE(IC_RESULT(ic));
2157     while (size--) {
2158 /*
2159         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2160         MOVA(l);       
2161         pic16_emitcode("cpl","a");
2162         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2163 */
2164         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2165               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2166         } else {
2167                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2168                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2169         }
2170         offset++;
2171
2172     }
2173
2174
2175 release:
2176     /* release the aops */
2177     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2178     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2179 }
2180 #endif
2181
2182 /*-----------------------------------------------------------------*/
2183 /* genUminusFloat - unary minus for floating points                */
2184 /*-----------------------------------------------------------------*/
2185 static void genUminusFloat(operand *op,operand *result)
2186 {
2187     int size ,offset =0 ;
2188     char *l;
2189
2190     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2191     /* for this we just need to flip the 
2192     first it then copy the rest in place */
2193     size = AOP_SIZE(op) - 1;
2194     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2195
2196     MOVA(l);    
2197
2198     pic16_emitcode("cpl","acc.7");
2199     pic16_aopPut(AOP(result),"a",3);    
2200
2201     while(size--) {
2202         pic16_aopPut(AOP(result),
2203                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2204                offset);
2205         offset++;
2206     }          
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* genUminus - unary minus code generation                         */
2211 /*-----------------------------------------------------------------*/
2212 static void genUminus (iCode *ic)
2213 {
2214   int size, i;
2215   sym_link *optype, *rtype;
2216
2217
2218   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2219   /* assign asmops */
2220   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2221   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2222
2223   /* if both in bit space then special
2224      case */
2225   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2226       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2227
2228     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2229     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2230     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2231
2232     goto release; 
2233   } 
2234
2235   optype = operandType(IC_LEFT(ic));
2236   rtype = operandType(IC_RESULT(ic));
2237
2238   /* if float then do float stuff */
2239   if (IS_FLOAT(optype)) {
2240     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2241     goto release;
2242   }
2243
2244   /* otherwise subtract from zero by taking the 2's complement */
2245   size = AOP_SIZE(IC_LEFT(ic));
2246
2247   for(i=0; i<size; i++) {
2248     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2249       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2250     else {
2251       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2252       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2253     }
2254   }
2255
2256   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2257   for(i=1; i<size; i++) {
2258     emitSKPNZ;
2259     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2260   }
2261
2262  release:
2263   /* release the aops */
2264   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2265   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2266 }
2267
2268 /*-----------------------------------------------------------------*/
2269 /* saveRegisters - will look for a call and save the registers     */
2270 /*-----------------------------------------------------------------*/
2271 static void saveRegisters(iCode *lic) 
2272 {
2273     int i;
2274     iCode *ic;
2275     bitVect *rsave;
2276     sym_link *dtype;
2277
2278     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2279     /* look for call */
2280     for (ic = lic ; ic ; ic = ic->next) 
2281         if (ic->op == CALL || ic->op == PCALL)
2282             break;
2283
2284     if (!ic) {
2285         fprintf(stderr,"found parameter push with no function call\n");
2286         return ;
2287     }
2288
2289     /* if the registers have been saved already then
2290     do nothing */
2291     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2292         return ;
2293
2294     /* find the registers in use at this time 
2295     and push them away to safety */
2296     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2297                           ic->rUsed);
2298
2299     ic->regsSaved = 1;
2300     if (options.useXstack) {
2301         if (bitVectBitValue(rsave,R0_IDX))
2302             pic16_emitcode("mov","b,r0");
2303         pic16_emitcode("mov","r0,%s",spname);
2304         for (i = 0 ; i < pic16_nRegs ; i++) {
2305             if (bitVectBitValue(rsave,i)) {
2306                 if (i == R0_IDX)
2307                     pic16_emitcode("mov","a,b");
2308                 else
2309                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2310                 pic16_emitcode("movx","@r0,a");
2311                 pic16_emitcode("inc","r0");
2312             }
2313         }
2314         pic16_emitcode("mov","%s,r0",spname);
2315         if (bitVectBitValue(rsave,R0_IDX))
2316             pic16_emitcode("mov","r0,b");           
2317     }// else
2318     //for (i = 0 ; i < pic16_nRegs ; i++) {
2319     //    if (bitVectBitValue(rsave,i))
2320     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2321     //}
2322
2323     dtype = operandType(IC_LEFT(ic));
2324     if (currFunc && dtype && 
2325         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2326         IFFUNC_ISISR(currFunc->type) &&
2327         !ic->bankSaved) 
2328
2329         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2330
2331 }
2332 /*-----------------------------------------------------------------*/
2333 /* unsaveRegisters - pop the pushed registers                      */
2334 /*-----------------------------------------------------------------*/
2335 static void unsaveRegisters (iCode *ic)
2336 {
2337     int i;
2338     bitVect *rsave;
2339
2340     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2341     /* find the registers in use at this time 
2342     and push them away to safety */
2343     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2344                           ic->rUsed);
2345     
2346     if (options.useXstack) {
2347         pic16_emitcode("mov","r0,%s",spname);   
2348         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2349             if (bitVectBitValue(rsave,i)) {
2350                 pic16_emitcode("dec","r0");
2351                 pic16_emitcode("movx","a,@r0");
2352                 if (i == R0_IDX)
2353                     pic16_emitcode("mov","b,a");
2354                 else
2355                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2356             }       
2357
2358         }
2359         pic16_emitcode("mov","%s,r0",spname);
2360         if (bitVectBitValue(rsave,R0_IDX))
2361             pic16_emitcode("mov","r0,b");
2362     } //else
2363     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2364     //    if (bitVectBitValue(rsave,i))
2365     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2366     //}
2367
2368 }  
2369
2370 #if 0  // patch 14
2371 /*-----------------------------------------------------------------*/
2372 /* pushSide -                                                      */
2373 /*-----------------------------------------------------------------*/
2374 static void pushSide(operand * oper, int size)
2375 {
2376         int offset = 0;
2377     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2378         while (size--) {
2379                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2380                 if (AOP_TYPE(oper) != AOP_REG &&
2381                     AOP_TYPE(oper) != AOP_DIR &&
2382                     strcmp(l,"a") ) {
2383                         pic16_emitcode("mov","a,%s",l);
2384                         pic16_emitcode("push","acc");
2385                 } else
2386                         pic16_emitcode("push","%s",l);
2387         }
2388 }
2389 #endif // patch 14
2390
2391 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2392 {
2393 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2394
2395         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2396                 pic16_emitpcode(POC_MOVFW, src);
2397                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2398         } else {
2399                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2400                         src, pic16_popGet(AOP(op), offset)));
2401         }
2402 }
2403
2404
2405 /*-----------------------------------------------------------------*/
2406 /* assignResultValue - assign results to oper, rescall==1 is       */
2407 /*                     called from genCall() or genPCall()         */
2408 /*-----------------------------------------------------------------*/
2409 static void assignResultValue(operand * oper, int rescall)
2410 {
2411   int size = AOP_SIZE(oper);
2412
2413         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2414         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2415
2416         if(rescall) {
2417                 /* assign result from a call/pcall function() */
2418                 
2419                 /* function results are stored in a special order,
2420                  * see top of file with Function return policy, or manual */
2421
2422                 if(size <= 4) {
2423                         /* 8-bits, result in WREG */
2424                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2425                         
2426                         if(size>1) {
2427                                 /* 16-bits, result in PRODL:WREG */
2428                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2429                         }
2430                         
2431                         if(size>2) {
2432                                 /* 24-bits, result in PRODH:PRODL:WREG */
2433                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2434                         }
2435                         
2436                         if(size>3) {
2437                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2438                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2439                         }
2440                 } else {
2441                         /* >32-bits, result on stack, and FSR0 points to beginning.
2442                          * Fix stack when done */
2443                          
2444                         while (size--) {
2445 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2446 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2447                 
2448                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2449                                 GpsuedoStkPtr++;
2450                         }
2451                         
2452                         /* fix stack */
2453                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2454                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2455                         if(STACK_MODEL_LARGE) {
2456                                 emitSKPNC;
2457                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2458                         }
2459                 }                       
2460         } else {        
2461                 if(!GpsuedoStkPtr) {
2462 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2463                         /* The last byte in the assignment is in W */
2464                         size--;
2465                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2466                         GpsuedoStkPtr++;
2467                 }
2468
2469                 while (size--) {
2470 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2471 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2472                 
2473                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2474                         GpsuedoStkPtr++;
2475
2476 #if 0
2477 #if STACK_SUPPORT
2478                 if(!USE_STACK)
2479                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2480 #else
2481                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2482 #endif
2483 #endif
2484
2485                 }
2486         }
2487                 
2488 }
2489
2490
2491 /*-----------------------------------------------------------------*/
2492 /* genIpush - genrate code for pushing this gets a little complex  */
2493 /*-----------------------------------------------------------------*/
2494 static void genIpush (iCode *ic)
2495 {
2496
2497   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2498 #if 0
2499     int size, offset = 0 ;
2500     char *l;
2501
2502
2503     /* if this is not a parm push : ie. it is spill push 
2504     and spill push is always done on the local stack */
2505     if (!ic->parmPush) {
2506
2507         /* and the item is spilt then do nothing */
2508         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2509             return ;
2510
2511         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2512         size = AOP_SIZE(IC_LEFT(ic));
2513         /* push it on the stack */
2514         while(size--) {
2515             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2516             if (*l == '#') {
2517                 MOVA(l);
2518                 l = "acc";
2519             }
2520             pic16_emitcode("push","%s",l);
2521         }
2522         return ;        
2523     }
2524
2525     /* this is a paramter push: in this case we call
2526     the routine to find the call and save those
2527     registers that need to be saved */   
2528     saveRegisters(ic);
2529
2530     /* then do the push */
2531     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2532
2533
2534         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2535     size = AOP_SIZE(IC_LEFT(ic));
2536
2537     while (size--) {
2538         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2539         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2540             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2541             strcmp(l,"a") ) {
2542             pic16_emitcode("mov","a,%s",l);
2543             pic16_emitcode("push","acc");
2544         } else
2545             pic16_emitcode("push","%s",l);
2546     }       
2547
2548     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2549 #endif
2550 }
2551
2552 /*-----------------------------------------------------------------*/
2553 /* genIpop - recover the registers: can happen only for spilling   */
2554 /*-----------------------------------------------------------------*/
2555 static void genIpop (iCode *ic)
2556 {
2557   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2558 #if 0
2559     int size,offset ;
2560
2561
2562     /* if the temp was not pushed then */
2563     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2564         return ;
2565
2566     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2567     size = AOP_SIZE(IC_LEFT(ic));
2568     offset = (size-1);
2569     while (size--) 
2570         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2571                                    FALSE,TRUE));
2572
2573     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2574 #endif
2575 }
2576
2577 /*-----------------------------------------------------------------*/
2578 /* unsaverbank - restores the resgister bank from stack            */
2579 /*-----------------------------------------------------------------*/
2580 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2581 {
2582   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2583 #if 0
2584     int i;
2585     asmop *aop ;
2586     regs *r = NULL;
2587
2588     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2589     if (popPsw) {
2590         if (options.useXstack) {
2591             aop = newAsmop(0);
2592             r = getFreePtr(ic,&aop,FALSE);
2593             
2594             
2595             pic16_emitcode("mov","%s,_spx",r->name);
2596             pic16_emitcode("movx","a,@%s",r->name);
2597             pic16_emitcode("mov","psw,a");
2598             pic16_emitcode("dec","%s",r->name);
2599             
2600         }else
2601             pic16_emitcode ("pop","psw");
2602     }
2603
2604     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2605         if (options.useXstack) {       
2606             pic16_emitcode("movx","a,@%s",r->name);
2607             //pic16_emitcode("mov","(%s+%d),a",
2608             //       regspic16[i].base,8*bank+regspic16[i].offset);
2609             pic16_emitcode("dec","%s",r->name);
2610
2611         } else 
2612           pic16_emitcode("pop",""); //"(%s+%d)",
2613         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2614     }
2615
2616     if (options.useXstack) {
2617
2618         pic16_emitcode("mov","_spx,%s",r->name);
2619         pic16_freeAsmop(NULL,aop,ic,TRUE);
2620
2621     }
2622 #endif 
2623 }
2624
2625 /*-----------------------------------------------------------------*/
2626 /* saverbank - saves an entire register bank on the stack          */
2627 /*-----------------------------------------------------------------*/
2628 static void saverbank (int bank, iCode *ic, bool pushPsw)
2629 {
2630   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2631 #if 0
2632     int i;
2633     asmop *aop ;
2634     regs *r = NULL;
2635
2636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2637     if (options.useXstack) {
2638
2639         aop = newAsmop(0);
2640         r = getFreePtr(ic,&aop,FALSE);  
2641         pic16_emitcode("mov","%s,_spx",r->name);
2642
2643     }
2644
2645     for (i = 0 ; i < pic16_nRegs ;i++) {
2646         if (options.useXstack) {
2647             pic16_emitcode("inc","%s",r->name);
2648             //pic16_emitcode("mov","a,(%s+%d)",
2649             //         regspic16[i].base,8*bank+regspic16[i].offset);
2650             pic16_emitcode("movx","@%s,a",r->name);           
2651         } else 
2652           pic16_emitcode("push","");// "(%s+%d)",
2653                      //regspic16[i].base,8*bank+regspic16[i].offset);
2654     }
2655     
2656     if (pushPsw) {
2657         if (options.useXstack) {
2658             pic16_emitcode("mov","a,psw");
2659             pic16_emitcode("movx","@%s,a",r->name);     
2660             pic16_emitcode("inc","%s",r->name);
2661             pic16_emitcode("mov","_spx,%s",r->name);       
2662             pic16_freeAsmop (NULL,aop,ic,TRUE);
2663             
2664         } else
2665             pic16_emitcode("push","psw");
2666         
2667         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2668     }
2669     ic->bankSaved = 1;
2670 #endif
2671 }
2672
2673
2674
2675 /*-----------------------------------------------------------------*/
2676 /* genCall - generates a call statement                            */
2677 /*-----------------------------------------------------------------*/
2678 static void genCall (iCode *ic)
2679 {
2680   sym_link *dtype;   
2681   int stackParms=0;
2682   
2683         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2684
2685         /* if caller saves & we have not saved then */
2686         if (!ic->regsSaved)
2687                 saveRegisters(ic);
2688
2689         /* if we are calling a function that is not using
2690          * the same register bank then we need to save the
2691          * destination registers on the stack */
2692         dtype = operandType(IC_LEFT(ic));
2693         if (currFunc && dtype && 
2694                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2695                 IFFUNC_ISISR(currFunc->type) &&
2696                 !ic->bankSaved) 
2697
2698                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2699
2700         /* if send set is not empty the assign */
2701         if (_G.sendSet) {
2702           iCode *sic;
2703
2704                 /* For the Pic port, there is no data stack.
2705                  * So parameters passed to functions are stored
2706                  * in registers. (The pCode optimizer will get
2707                  * rid of most of these :). */
2708
2709           int psuedoStkPtr=-1; 
2710           int firstTimeThruLoop = 1;
2711
2712                 _G.sendSet = reverseSet(_G.sendSet);
2713
2714                 /* First figure how many parameters are getting passed */
2715                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2716                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2717                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2718                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2719                 }
2720
2721                 stackParms = psuedoStkPtr;
2722
2723                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2724                   int size, offset = 0;
2725
2726                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2727                         size = AOP_SIZE(IC_LEFT(sic));
2728
2729                         while (size--) {
2730                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2731                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2732                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2733
2734                                 if(!firstTimeThruLoop) {
2735                                         /* If this is not the first time we've been through the loop
2736                                          * then we need to save the parameter in a temporary
2737                                          * register. The last byte of the last parameter is
2738                                          * passed in W. */
2739
2740                                         pushw();
2741                                         --psuedoStkPtr;         // sanity check
2742                                 }
2743                         
2744                                 firstTimeThruLoop=0;
2745
2746                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2747                                 offset++;
2748                         }
2749                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2750                 }
2751                 _G.sendSet = NULL;
2752         }
2753
2754         /* make the call */
2755         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2756                         OP_SYMBOL(IC_LEFT(ic))->rname :
2757                         OP_SYMBOL(IC_LEFT(ic))->name));
2758
2759         GpsuedoStkPtr=0;
2760         /* if we need assign a result value */
2761         if ((IS_ITEMP(IC_RESULT(ic)) && 
2762                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2763                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2764                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2765
2766                 _G.accInUse++;
2767                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2768                 _G.accInUse--;
2769
2770                 assignResultValue(IC_RESULT(ic), 1);
2771
2772                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2773                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2774                 
2775                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2776         }
2777
2778         if(stackParms>0) {
2779                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2780                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2781                 if(STACK_MODEL_LARGE) {
2782                         emitSKPNC;
2783                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2784                 }
2785         }
2786
2787         /* adjust the stack for parameters if required */
2788 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2789
2790         if (ic->parmBytes) {
2791           int i;
2792
2793                 if (ic->parmBytes > 3) {
2794                         pic16_emitcode("mov","a,%s",spname);
2795                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2796                         pic16_emitcode("mov","%s,a",spname);
2797                 } else 
2798                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2799                                 pic16_emitcode("dec","%s",spname);
2800         }
2801
2802         /* if register bank was saved then pop them */
2803         if (ic->bankSaved)
2804                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2805
2806         /* if we hade saved some registers then unsave them */
2807         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2808                 unsaveRegisters (ic);
2809 }
2810
2811
2812
2813 /*-----------------------------------------------------------------*/   // patch 14
2814 /* genPcall - generates a call by pointer statement                */
2815 /*-----------------------------------------------------------------*/
2816
2817 // new version, created from genCall
2818
2819 static void genPcall (iCode *ic)
2820 {
2821   sym_link *dtype;   
2822   int stackParms=0;
2823   symbol *retlbl = newiTempLabel(NULL);
2824   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2825   
2826         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2827
2828         /* if caller saves & we have not saved then */
2829         if (!ic->regsSaved)
2830                 saveRegisters(ic);
2831
2832         /* if we are calling a function that is not using
2833          * the same register bank then we need to save the
2834          * destination registers on the stack */
2835         dtype = operandType(IC_LEFT(ic));
2836         if (currFunc && dtype && 
2837                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2838                 IFFUNC_ISISR(currFunc->type) &&
2839                 !ic->bankSaved) 
2840
2841                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2842
2843         /* if send set is not empty the assign */
2844         if (_G.sendSet) {
2845           iCode *sic;
2846
2847                 /* For the Pic port, there is no data stack.
2848                  * So parameters passed to functions are stored
2849                  * in registers. (The pCode optimizer will get
2850                  * rid of most of these :). */
2851
2852           int psuedoStkPtr=-1; 
2853           int firstTimeThruLoop = 1;
2854
2855                 _G.sendSet = reverseSet(_G.sendSet);
2856
2857                 /* First figure how many parameters are getting passed */
2858                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2859                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2860                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2861                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2862                 }
2863
2864                 stackParms = psuedoStkPtr;
2865
2866                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2867                   int size, offset = 0;
2868
2869                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2870                         size = AOP_SIZE(IC_LEFT(sic));
2871
2872                         while (size--) {
2873                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2874                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2875                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2876
2877                                 if(!firstTimeThruLoop) {
2878                                         /* If this is not the first time we've been through the loop
2879                                          * then we need to save the parameter in a temporary
2880                                          * register. The last byte of the last parameter is
2881                                          * passed in W. */
2882
2883                                         pushw();
2884                                         --psuedoStkPtr;         // sanity check
2885                                 }
2886                         
2887                                 firstTimeThruLoop=0;
2888
2889                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2890                                 offset++;
2891                         }
2892                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2893                 }
2894                 _G.sendSet = NULL;
2895         }
2896
2897         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2898
2899         // push return address
2900         // push $ on return stack, then replace with retlbl
2901
2902         // Note: retlbl is supplied as dummy operand to PUSH
2903         // This has the nice side effect of keeping the label from being optimized out :o)
2904         pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));      
2905
2906         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2907         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2908         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2909         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2910         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2911         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2912
2913         /* make the call by writing the pointer into pc */
2914 // FIXME Disabled writes to PCLATU because of gpsim problems
2915 #if 0
2916         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2917 #endif
2918         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2919         // note: MOVFF to PCL not allowed
2920         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2921         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2922
2923         /* return address is here: (X) */
2924         pic16_emitpLabel(retlbl->key);
2925
2926         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2927
2928         GpsuedoStkPtr=0;
2929         /* if we need assign a result value */
2930         if ((IS_ITEMP(IC_RESULT(ic)) && 
2931                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2932                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2933                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2934
2935                 _G.accInUse++;
2936                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2937                 _G.accInUse--;
2938
2939                 assignResultValue(IC_RESULT(ic), 1);
2940
2941                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2942                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2943                 
2944                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2945         }
2946
2947         if(stackParms>0) {
2948                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2949                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2950                 if(STACK_MODEL_LARGE) {
2951                         emitSKPNC;
2952                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2953                 }
2954         }
2955
2956         /* adjust the stack for parameters if required */
2957 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2958
2959         if (ic->parmBytes) {
2960           int i;
2961
2962                 if (ic->parmBytes > 3) {
2963                         pic16_emitcode("mov","a,%s",spname);
2964                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2965                         pic16_emitcode("mov","%s,a",spname);
2966                 } else 
2967                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2968                                 pic16_emitcode("dec","%s",spname);
2969         }
2970
2971         /* if register bank was saved then pop them */
2972         if (ic->bankSaved)
2973                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2974
2975         /* if we hade saved some registers then unsave them */
2976         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2977                 unsaveRegisters (ic);
2978 }
2979
2980
2981 #if 0                                                                           // patch 14
2982 // old version, kept for reference
2983
2984 /*-----------------------------------------------------------------*/
2985 /* genPcall - generates a call by pointer statement                */
2986 /*-----------------------------------------------------------------*/
2987 static void genPcall (iCode *ic)
2988 {
2989     sym_link *dtype;
2990     symbol *rlbl = newiTempLabel(NULL);
2991
2992
2993     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2994     /* if caller saves & we have not saved then */
2995     if (!ic->regsSaved)
2996         saveRegisters(ic);
2997
2998     /* if we are calling a function that is not using
2999     the same register bank then we need to save the
3000     destination registers on the stack */
3001     dtype = operandType(IC_LEFT(ic));
3002     if (currFunc && dtype && 
3003         IFFUNC_ISISR(currFunc->type) &&
3004         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3005         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3006
3007
3008     /* push the return address on to the stack */
3009     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3010     pic16_emitcode("push","acc");    
3011     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3012     pic16_emitcode("push","acc");
3013     
3014     if (options.model == MODEL_FLAT24)
3015     {
3016         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3017         pic16_emitcode("push","acc");    
3018     }
3019
3020     /* now push the calling address */
3021     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3022
3023     pushSide(IC_LEFT(ic), FPTRSIZE);
3024
3025     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3026
3027     /* if send set is not empty the assign */
3028     if (_G.sendSet) {
3029         iCode *sic ;
3030
3031         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3032              sic = setNextItem(_G.sendSet)) {
3033             int size, offset = 0;
3034             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3035             size = AOP_SIZE(IC_LEFT(sic));
3036             while (size--) {
3037                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3038                                 FALSE,FALSE);
3039                 if (strcmp(l,fReturn[offset]))
3040                     pic16_emitcode("mov","%s,%s",
3041                              fReturn[offset],
3042                              l);
3043                 offset++;
3044             }
3045             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3046         }
3047         _G.sendSet = NULL;
3048     }
3049
3050     pic16_emitcode("ret","");
3051     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3052
3053
3054     /* if we need assign a result value */
3055     if ((IS_ITEMP(IC_RESULT(ic)) &&
3056          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3057           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3058         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3059
3060         _G.accInUse++;
3061         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3062         _G.accInUse--;
3063         
3064         assignResultValue(IC_RESULT(ic), 1);
3065
3066         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3067     }
3068
3069     /* adjust the stack for parameters if 
3070     required */
3071     if (ic->parmBytes) {
3072         int i;
3073         if (ic->parmBytes > 3) {
3074             pic16_emitcode("mov","a,%s",spname);
3075             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3076             pic16_emitcode("mov","%s,a",spname);
3077         } else 
3078             for ( i = 0 ; i <  ic->parmBytes ;i++)
3079                 pic16_emitcode("dec","%s",spname);
3080
3081     }
3082
3083     /* if register bank was saved then unsave them */
3084     if (currFunc && dtype && 
3085         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3086         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3087
3088     /* if we hade saved some registers then
3089     unsave them */
3090     if (ic->regsSaved)
3091         unsaveRegisters (ic);
3092
3093 }
3094 #endif                                                                          // patch 14
3095
3096
3097 /*-----------------------------------------------------------------*/
3098 /* resultRemat - result  is rematerializable                       */
3099 /*-----------------------------------------------------------------*/
3100 static int resultRemat (iCode *ic)
3101 {
3102   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3103   if (SKIP_IC(ic) || ic->op == IFX)
3104     return 0;
3105
3106   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3107     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3108     if (sym->remat && !POINTER_SET(ic)) 
3109       return 1;
3110   }
3111
3112   return 0;
3113 }
3114
3115 #if defined(__BORLANDC__) || defined(_MSC_VER)
3116 #define STRCASECMP stricmp
3117 #else
3118 #define STRCASECMP strcasecmp
3119 #endif
3120
3121 #if 0
3122 /*-----------------------------------------------------------------*/
3123 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3124 /*-----------------------------------------------------------------*/
3125 static bool inExcludeList(char *s)
3126 {
3127   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3128     int i =0;
3129     
3130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3131     if (options.excludeRegs[i] &&
3132     STRCASECMP(options.excludeRegs[i],"none") == 0)
3133         return FALSE ;
3134
3135     for ( i = 0 ; options.excludeRegs[i]; i++) {
3136         if (options.excludeRegs[i] &&
3137         STRCASECMP(s,options.excludeRegs[i]) == 0)
3138             return TRUE;
3139     }
3140     return FALSE ;
3141 }
3142 #endif
3143
3144 /*-----------------------------------------------------------------*/
3145 /* genFunction - generated code for function entry                 */
3146 /*-----------------------------------------------------------------*/
3147 static void genFunction (iCode *ic)
3148 {
3149   symbol *sym;
3150   sym_link *ftype;
3151   
3152         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3153
3154         labelOffset += (max_key+4);
3155         max_key=0;
3156         GpsuedoStkPtr=0;
3157         _G.nRegsSaved = 0;
3158
3159         ftype = operandType(IC_LEFT(ic));
3160         sym = OP_SYMBOL(IC_LEFT(ic));
3161
3162         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3163                 /* create an absolute section at the interrupt vector:
3164                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3165           symbol *asym;
3166           char asymname[128];
3167           pBlock *apb;
3168
3169                 {
3170                   int i, found=-1;
3171
3172                         sym = OP_SYMBOL( IC_LEFT(ic));
3173                         for(i=0;i<=2;i++) {
3174                                 if(interrupts[i]->name
3175                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3176                                         found = i;
3177                                         break;
3178                                 }
3179                         }
3180                         
3181                         if(found == -1) {
3182                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3183                                         __FILE__, __LINE__, sym->name);
3184                                 assert( 0 );
3185                         }
3186                         _G.interruptvector = found;
3187                 }
3188
3189                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3190                 asym = newSymbol(asymname, 0);
3191
3192                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3193                 pic16_addpBlock( apb );
3194
3195                 pic16_addpCode2pBlock(apb,
3196                         pic16_newpCodeCharP(";-----------------------------------------"));
3197
3198
3199                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3200
3201                 pic16_addpCode2pBlock(apb,
3202                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3203                 
3204                 /* mark the end of this tiny function */
3205                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3206
3207                 {
3208                   absSym *abSym;
3209
3210                         abSym = Safe_calloc(1, sizeof(absSym));
3211                         abSym->name = Safe_strdup( asymname );
3212
3213                         switch( _G.interruptvector ) {
3214                                 case 0: abSym->address = 0x000000; break;
3215                                 case 1: abSym->address = 0x000008; break;
3216                                 case 2: abSym->address = 0x000018; break;
3217                         }
3218
3219                         addSet(&absSymSet, abSym);
3220                 }
3221         }
3222
3223
3224         /* create the function header */
3225         pic16_emitcode(";","-----------------------------------------");
3226         pic16_emitcode(";"," function %s",sym->name);
3227         pic16_emitcode(";","-----------------------------------------");
3228
3229         pic16_emitcode("","%s:",sym->rname);
3230         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3231
3232
3233         {
3234           absSym *ab;
3235
3236                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3237                         if(!strcmp(ab->name, sym->name)) {
3238                                 pic16_pBlockConvert2Absolute(pb);
3239                                 break;
3240                         }
3241
3242         }
3243
3244
3245         if(IFFUNC_ISNAKED(ftype)) {
3246                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3247                 return;
3248         }
3249         
3250         /* if critical function then turn interrupts off */
3251         if (IFFUNC_ISCRITICAL(ftype))
3252                 pic16_emitcode("clr","ea");
3253
3254         /* if this is an interrupt service routine then
3255          * save acc, b, dpl, dph  */
3256         if (IFFUNC_ISISR(sym->type)) {
3257           int i;
3258                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3259                 if(!(_G.interruptvector == 1)) {
3260
3261                         /* do not save WREG,STATUS,BSR for high priority interrupts
3262                          * because they are stored in the hardware shadow registers already */
3263                          
3264                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3265                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3266                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3267                 }
3268
3269                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3270                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3271                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3272                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3273
3274 //                pic16_pBlockConvert2ISR(pb);
3275                 
3276                 /* if any registers used */
3277                 if (sym->regsUsed) {
3278                         /* save the registers used */
3279                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3280                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3281                                 if (bitVectBitValue(sym->regsUsed,i)) {
3282 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3283 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3284 //                                                      pic16_regWithIdx(i)->name);
3285
3286                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3287                                         _G.nRegsSaved++;
3288                                 }
3289                         }
3290                 }
3291         } else {
3292                 /* emit code to setup stack frame if user enabled,
3293                  * and function is not main() */
3294          
3295 //              fprintf(stderr, "function name: %s\n", sym->name);
3296                 if(strcmp(sym->name, "main")) {
3297                         if(!options.ommitFramePtr || sym->regsUsed) {
3298                         /* setup the stack frame */
3299                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3300                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3301                                 if(STACK_MODEL_LARGE)
3302                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3303                         }
3304                 }
3305
3306                 /* if callee-save to be used for this function
3307                 * then save the registers being used in this function */
3308                 if (IFFUNC_CALLEESAVES(sym->type)) {
3309                   int i;
3310             
3311 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
3312                         
3313                         /* if any registers used */
3314                         if (sym->regsUsed) {
3315                                 /* save the registers used */
3316                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3317                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3318                                         if (bitVectBitValue(sym->regsUsed,i)) {
3319
3320 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3321 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3322 //                                                              pic16_regWithIdx(i)->name);
3323
3324                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3325
3326 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3327 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3328 //                                                      &pic16_pc_postdec1, 0));
3329
3330                                                 _G.nRegsSaved++;
3331                                         }
3332                                 }
3333                         }
3334                 }
3335         }
3336
3337
3338         
3339 #if 0
3340         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3341
3342                 if (options.useXstack) {
3343                         pic16_emitcode("mov","r0,%s",spname);
3344                         pic16_emitcode("mov","a,_bp");
3345                         pic16_emitcode("movx","@r0,a");
3346                         pic16_emitcode("inc","%s",spname);
3347                 } else {
3348                         /* set up the stack */
3349                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3350                 }
3351                 pic16_emitcode ("mov","_bp,%s",spname);
3352         }
3353 #endif
3354         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3355
3356         /* adjust the stack for the function */
3357         if (sym->stack) {
3358           int i = sym->stack;
3359
3360                 if (i > 127 ) 
3361                         werror(W_STACK_OVERFLOW,sym->name);
3362
3363                 if (i > 3 && sym->recvSize < 4) {              
3364                         pic16_emitcode ("mov","a,sp");
3365                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3366                         pic16_emitcode ("mov","sp,a");
3367                 } else
3368                         while(i--)
3369                                 pic16_emitcode("inc","sp");
3370         }
3371
3372         if (sym->xstack) {
3373                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3374
3375                 pic16_emitcode ("mov","a,_spx");
3376                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3377                 pic16_emitcode ("mov","_spx,a");
3378         }
3379     
3380 }
3381
3382 /*-----------------------------------------------------------------*/
3383 /* genEndFunction - generates epilogue for functions               */
3384 /*-----------------------------------------------------------------*/
3385 static void genEndFunction (iCode *ic)
3386 {
3387     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3388
3389     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3390
3391     if(IFFUNC_ISNAKED(sym->type)) {
3392         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3393         return;
3394     }
3395
3396 #if 0
3397     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3398     {
3399         pic16_emitcode ("mov","%s,_bp",spname);
3400     }
3401 #endif
3402
3403     /* if use external stack but some variables were
3404     added to the local stack then decrement the
3405     local stack */
3406     if (options.useXstack && sym->stack) {      
3407         pic16_emitcode("mov","a,sp");
3408         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3409         pic16_emitcode("mov","sp,a");
3410     }
3411
3412
3413 #if 0
3414     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3415         if (options.useXstack) {
3416             pic16_emitcode("mov","r0,%s",spname);
3417             pic16_emitcode("movx","a,@r0");
3418             pic16_emitcode("mov","_bp,a");
3419             pic16_emitcode("dec","%s",spname);
3420         }
3421         else
3422         {
3423             pic16_emitcode ("pop","_bp");
3424         }
3425     }
3426 #endif
3427
3428     /* restore the register bank  */    
3429     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3430         pic16_emitcode ("pop","psw");
3431
3432         if (IFFUNC_ISISR(sym->type)) {
3433
3434                 /* now we need to restore the registers */
3435                 
3436                 /* if any registers used */
3437                 if (sym->regsUsed) {
3438                   int i;
3439
3440                         /* restore registers used */
3441                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3442                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3443                                 if (bitVectBitValue(sym->regsUsed,i)) {
3444 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3445 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3446 //                                                      pic16_regWithIdx(i)->name);
3447         
3448                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3449                                                         &pic16_pc_preinc1,
3450                                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3451                                 }
3452                         }
3453                 }
3454         
3455                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3456                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3457                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3458                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3459
3460                 if(!(_G.interruptvector == 1)) {
3461                         /* do not restore interrupt vector for WREG,STATUS,BSR
3462                          * for high priority interrupt, see genFunction */
3463                          
3464                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3465                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3466                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3467                 }
3468         
3469                 _G.interruptvector = 0;         /* sanity check */
3470
3471 //              pic16_pBlockConvert2ISR(pb);
3472
3473
3474                 /* if debug then send end of function */
3475 /*      if (options.debug && currFunc)  */
3476                 if (currFunc) {
3477                         _G.debugLine = 1;
3478                         pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3479                                         FileBaseName(ic->filename),currFunc->lastLine,
3480                                         ic->level,ic->block); 
3481                         if (IS_STATIC(currFunc->etype))     
3482                                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3483                         else
3484                                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3485                         _G.debugLine = 0;
3486                 }
3487         
3488 #if 0
3489                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3490                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3491                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3492                 pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3493                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3494 #endif
3495
3496                 pic16_emitpcodeNULLop(POC_RETFIE);
3497         }
3498         else {
3499                 if (IFFUNC_ISCRITICAL(sym->type))
3500                         pic16_emitcode("setb","ea");
3501         
3502         /* if any registers used */
3503         if (sym->regsUsed) {
3504           int i;
3505                 /* save the registers used */
3506                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3507                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3508                         if (bitVectBitValue(sym->regsUsed,i)) {
3509 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3510 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3511 //                                              pic16_regWithIdx(i)->name);
3512         
3513                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3514                                         &pic16_pc_preinc1,
3515                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3516                         }
3517                 }
3518         }
3519         
3520
3521         /* if debug then send end of function */
3522         if (currFunc) {
3523             _G.debugLine = 1;
3524             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3525                      FileBaseName(ic->filename),currFunc->lastLine,
3526                      ic->level,ic->block); 
3527             if (IS_STATIC(currFunc->etype))         
3528                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3529             else
3530                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3531             _G.debugLine = 0;
3532         }
3533
3534         /* insert code to restore stack frame, if user enabled it
3535          * and function is not main() */
3536          
3537         if(strcmp(sym->name, "main")) {
3538                 if(!options.ommitFramePtr || sym->regsUsed) {
3539                         /* restore stack frame */
3540                         if(STACK_MODEL_LARGE)
3541                                 pic16_emitpcode(POC_MOVFF,
3542                                         pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3543                         pic16_emitpcode(POC_MOVFF,
3544                                         pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3545                 }
3546         }
3547
3548         pic16_emitcode ("return","");
3549         pic16_emitpcodeNULLop(POC_RETURN);
3550
3551         /* Mark the end of a function */
3552         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3553     }
3554
3555 }
3556
3557
3558 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3559 {
3560 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
3561
3562         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3563                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3564                 pic16_emitpcode(POC_MOVWF, dest);
3565         } else {
3566                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3567                         pic16_popGet(AOP(op), offset), dest));
3568         }
3569 }
3570
3571 /*-----------------------------------------------------------------*/
3572 /* genRet - generate code for return statement                     */
3573 /*-----------------------------------------------------------------*/
3574 static void genRet (iCode *ic)
3575 {
3576   int size;
3577   operand *left;
3578
3579         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3580         /* if we have no return value then
3581          * just generate the "ret" */
3582         
3583         if (!IC_LEFT(ic)) 
3584                 goto jumpret;       
3585     
3586         /* we have something to return then
3587          * move the return value into place */
3588         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3589         size = AOP_SIZE(IC_LEFT(ic));
3590
3591         if(size <= 4) {
3592                 if(size>3) {
3593                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3594 //                      pic16_emitpcode(POC_MOVFF,
3595 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3596                 }
3597                 if(size>2) {
3598                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3599 //                      pic16_emitpcode(POC_MOVFF,
3600 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3601                 }
3602                 if(size>1) {
3603                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3604 //                      pic16_emitpcode(POC_MOVFF,
3605 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3606                 }
3607
3608 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3609
3610                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3611 //              pic16_emitpcode(POC_MOVFF,
3612 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3613
3614         } else {
3615                 /* >32-bits, setup stack and FSR0 */
3616                 while (size--) {
3617 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3618 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3619
3620                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3621
3622 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3623                         GpsuedoStkPtr++;
3624                 }
3625                         
3626                 /* setup FSR0 */
3627                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3628                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3629
3630                 if(STACK_MODEL_LARGE) {
3631                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3632                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3633                 } else {
3634                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3635                 }
3636         }
3637                                 
3638 #if 0
3639         /* old code, left here for reference -- VR */    
3640         while (size--) {
3641           char *l ;
3642
3643                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3644                         /* #NOCHANGE */
3645                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3646                         pic16_emitpcomment("push %s",l);
3647                         pushed++;
3648                 } else {
3649                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3650                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3651                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3652                         
3653                         if (strcmp(fReturn[offset],l)) {
3654                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3655                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3656                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3657                                 } else {
3658                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3659                                 }
3660                                 
3661                                 if(size) {
3662                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3663                                 }
3664                                 offset++;
3665                         }
3666                 }
3667         }    
3668
3669         if (pushed) {
3670                 while(pushed) {
3671                         pushed--;
3672                         if (strcmp(fReturn[pushed],"a"))
3673                                 pic16_emitcode("pop",fReturn[pushed]);
3674                         else
3675                                 pic16_emitcode("pop","acc");
3676                 }
3677         }
3678 #endif
3679
3680
3681         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3682     
3683 jumpret:
3684         /* generate a jump to the return label
3685          * if the next is not the return statement */
3686         if (!(ic->next && ic->next->op == LABEL
3687                 && IC_LABEL(ic->next) == returnLabel)) {
3688         
3689                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3690                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3691         }
3692 }
3693
3694 /*-----------------------------------------------------------------*/
3695 /* genLabel - generates a label                                    */
3696 /*-----------------------------------------------------------------*/
3697 static void genLabel (iCode *ic)
3698 {
3699     /* special case never generate */
3700     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3701     if (IC_LABEL(ic) == entryLabel)
3702         return ;
3703
3704     pic16_emitpLabel(IC_LABEL(ic)->key);
3705     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3706 }
3707
3708 /*-----------------------------------------------------------------*/
3709 /* genGoto - generates a goto                                      */
3710 /*-----------------------------------------------------------------*/
3711 //tsd
3712 static void genGoto (iCode *ic)
3713 {
3714   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3715   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3716 }
3717
3718
3719 /*-----------------------------------------------------------------*/
3720 /* genMultbits :- multiplication of bits                           */
3721 /*-----------------------------------------------------------------*/
3722 static void genMultbits (operand *left, 
3723                          operand *right, 
3724                          operand *result)
3725 {
3726   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3727
3728   if(!pic16_sameRegs(AOP(result),AOP(right)))
3729     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3730
3731   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3732   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3733   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3734
3735 }
3736
3737
3738 /*-----------------------------------------------------------------*/
3739 /* genMultOneByte : 8 bit multiplication & division                */
3740 /*-----------------------------------------------------------------*/
3741 static void genMultOneByte (operand *left,
3742                             operand *right,
3743                             operand *result)
3744 {
3745   sym_link *opetype = operandType(result);
3746
3747   // symbol *lbl ;
3748   int size,offset;
3749
3750   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3751   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3752   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3753
3754   /* (if two literals, the value is computed before) */
3755   /* if one literal, literal on the right */
3756   if (AOP_TYPE(left) == AOP_LIT){
3757     operand *t = right;
3758     right = left;
3759     left = t;
3760   }
3761
3762   size = AOP_SIZE(result);
3763   if(size == 1) {
3764
3765     if (AOP_TYPE(right) == AOP_LIT){
3766       pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3767                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3768                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3769                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3770     } else {
3771       pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3772                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3773                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3774                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3775     }
3776     pic16_genMult8X8_8 (left, right,result);
3777   } else {  // (size > 1)
3778
3779     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3780                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3781                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3782                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3783
3784     if (SPEC_USIGN(opetype)){
3785       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3786       pic16_genUMult8X8_16 (left, right, result, NULL);
3787
3788       if (size > 2) {
3789         /* for filling the MSBs */
3790         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3791         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3792       }
3793     }
3794     else{
3795       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3796
3797       pic16_emitcode("mov","a,b");
3798
3799       /* adjust the MSB if left or right neg */
3800
3801       /* if one literal */
3802       if (AOP_TYPE(right) == AOP_LIT){
3803         pic16_emitcode("multiply ","right is a lit");
3804         /* AND literal negative */
3805         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3806           /* adjust MSB (c==0 after mul) */
3807           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3808         }
3809       }
3810       else{
3811         pic16_genSMult8X8_16 (left, right, result, NULL);
3812       }
3813
3814       if(size > 2){
3815         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3816         /* get the sign */
3817         pic16_emitcode("rlc","a");
3818         pic16_emitcode("subb","a,acc");
3819       }
3820     }
3821
3822     size -= 2;   
3823     offset = 2;
3824     if (size > 0)
3825       while (size--)
3826         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3827     //pic16_aopPut(AOP(result),"a",offset++);
3828   }
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* genMult - generates code for multiplication                     */
3833 /*-----------------------------------------------------------------*/
3834 static void genMult (iCode *ic)
3835 {
3836     operand *left = IC_LEFT(ic);
3837     operand *right = IC_RIGHT(ic);
3838     operand *result= IC_RESULT(ic);   
3839
3840     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3841     /* assign the amsops */
3842     pic16_aopOp (left,ic,FALSE);
3843     pic16_aopOp (right,ic,FALSE);
3844     pic16_aopOp (result,ic,TRUE);
3845
3846   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3847
3848     /* special cases first */
3849     /* both are bits */
3850     if (AOP_TYPE(left) == AOP_CRY &&
3851         AOP_TYPE(right)== AOP_CRY) {
3852         genMultbits(left,right,result);
3853         goto release ;
3854     }
3855
3856     /* if both are of size == 1 */
3857     if (AOP_SIZE(left) == 1 &&
3858         AOP_SIZE(right) == 1 ) {
3859         genMultOneByte(left,right,result);
3860         goto release ;
3861     }
3862
3863     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3864
3865     /* should have been converted to function call */
3866         assert(0) ;
3867
3868 release :
3869     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3870     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3871     pic16_freeAsmop(result,NULL,ic,TRUE); 
3872 }
3873
3874 /*-----------------------------------------------------------------*/
3875 /* genDivbits :- division of bits                                  */
3876 /*-----------------------------------------------------------------*/
3877 static void genDivbits (operand *left, 
3878                         operand *right, 
3879                         operand *result)
3880 {
3881
3882     char *l;
3883
3884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3885     /* the result must be bit */    
3886     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3887     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3888
3889     MOVA(l);    
3890
3891     pic16_emitcode("div","ab");
3892     pic16_emitcode("rrc","a");
3893     pic16_aopPut(AOP(result),"c",0);
3894 }
3895
3896 /*-----------------------------------------------------------------*/
3897 /* genDivOneByte : 8 bit division                                  */
3898 /*-----------------------------------------------------------------*/
3899 static void genDivOneByte (operand *left,
3900                            operand *right,
3901                            operand *result)
3902 {
3903     sym_link *opetype = operandType(result);
3904     char *l ;
3905     symbol *lbl ;
3906     int size,offset;
3907
3908     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3909     size = AOP_SIZE(result) - 1;
3910     offset = 1;
3911     /* signed or unsigned */
3912     if (SPEC_USIGN(opetype)) {
3913         /* unsigned is easy */
3914         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3915         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3916         MOVA(l);        
3917         pic16_emitcode("div","ab");
3918         pic16_aopPut(AOP(result),"a",0);
3919         while (size--)
3920             pic16_aopPut(AOP(result),zero,offset++);
3921         return ;
3922     }
3923
3924     /* signed is a little bit more difficult */
3925
3926     /* save the signs of the operands */
3927     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3928     MOVA(l);    
3929     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3930     pic16_emitcode("push","acc"); /* save it on the stack */
3931
3932     /* now sign adjust for both left & right */
3933     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3934     MOVA(l);       
3935     lbl = newiTempLabel(NULL);
3936     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3937     pic16_emitcode("cpl","a");   
3938     pic16_emitcode("inc","a");
3939     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3940     pic16_emitcode("mov","b,a");
3941
3942     /* sign adjust left side */
3943     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3944     MOVA(l);
3945
3946     lbl = newiTempLabel(NULL);
3947     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3948     pic16_emitcode("cpl","a");
3949     pic16_emitcode("inc","a");
3950     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3951
3952     /* now the division */
3953     pic16_emitcode("div","ab");
3954     /* we are interested in the lower order
3955     only */
3956     pic16_emitcode("mov","b,a");
3957     lbl = newiTempLabel(NULL);
3958     pic16_emitcode("pop","acc");   
3959     /* if there was an over flow we don't 
3960     adjust the sign of the result */
3961     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3962     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3963     CLRC;
3964     pic16_emitcode("clr","a");
3965     pic16_emitcode("subb","a,b");
3966     pic16_emitcode("mov","b,a");
3967     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3968
3969     /* now we are done */
3970     pic16_aopPut(AOP(result),"b",0);
3971     if(size > 0){
3972         pic16_emitcode("mov","c,b.7");
3973         pic16_emitcode("subb","a,acc");   
3974     }
3975     while (size--)
3976         pic16_aopPut(AOP(result),"a",offset++);
3977
3978 }
3979
3980 /*-----------------------------------------------------------------*/
3981 /* genDiv - generates code for division                            */
3982 /*-----------------------------------------------------------------*/
3983 static void genDiv (iCode *ic)
3984 {
3985     operand *left = IC_LEFT(ic);
3986     operand *right = IC_RIGHT(ic);
3987     operand *result= IC_RESULT(ic);   
3988
3989     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3990     /* assign the amsops */
3991     pic16_aopOp (left,ic,FALSE);
3992     pic16_aopOp (right,ic,FALSE);
3993     pic16_aopOp (result,ic,TRUE);
3994
3995     /* special cases first */
3996     /* both are bits */
3997     if (AOP_TYPE(left) == AOP_CRY &&
3998         AOP_TYPE(right)== AOP_CRY) {
3999         genDivbits(left,right,result);
4000         goto release ;
4001     }
4002
4003     /* if both are of size == 1 */
4004     if (AOP_SIZE(left) == 1 &&
4005         AOP_SIZE(right) == 1 ) {
4006         genDivOneByte(left,right,result);
4007         goto release ;
4008     }
4009
4010     /* should have been converted to function call */
4011     assert(0);
4012 release :
4013     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4014     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4015     pic16_freeAsmop(result,NULL,ic,TRUE); 
4016 }
4017
4018 /*-----------------------------------------------------------------*/
4019 /* genModbits :- modulus of bits                                   */
4020 /*-----------------------------------------------------------------*/
4021 static void genModbits (operand *left, 
4022                         operand *right, 
4023                         operand *result)
4024 {
4025
4026     char *l;
4027
4028     /* the result must be bit */    
4029     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4030     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4031
4032     MOVA(l);       
4033
4034     pic16_emitcode("div","ab");
4035     pic16_emitcode("mov","a,b");
4036     pic16_emitcode("rrc","a");
4037     pic16_aopPut(AOP(result),"c",0);
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genModOneByte : 8 bit modulus                                   */
4042 /*-----------------------------------------------------------------*/
4043 static void genModOneByte (operand *left,
4044                            operand *right,
4045                            operand *result)
4046 {
4047     sym_link *opetype = operandType(result);
4048     char *l ;
4049     symbol *lbl ;
4050
4051     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4052     /* signed or unsigned */
4053     if (SPEC_USIGN(opetype)) {
4054         /* unsigned is easy */
4055         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4056         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4057         MOVA(l);    
4058         pic16_emitcode("div","ab");
4059         pic16_aopPut(AOP(result),"b",0);
4060         return ;
4061     }
4062
4063     /* signed is a little bit more difficult */
4064
4065     /* save the signs of the operands */
4066     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4067     MOVA(l);
4068
4069     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4070     pic16_emitcode("push","acc"); /* save it on the stack */
4071
4072     /* now sign adjust for both left & right */
4073     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4074     MOVA(l);
4075
4076     lbl = newiTempLabel(NULL);
4077     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4078     pic16_emitcode("cpl","a");   
4079     pic16_emitcode("inc","a");
4080     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4081     pic16_emitcode("mov","b,a"); 
4082
4083     /* sign adjust left side */
4084     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4085     MOVA(l);
4086
4087     lbl = newiTempLabel(NULL);
4088     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4089     pic16_emitcode("cpl","a");   
4090     pic16_emitcode("inc","a");
4091     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4092
4093     /* now the multiplication */
4094     pic16_emitcode("div","ab");
4095     /* we are interested in the lower order
4096     only */
4097     lbl = newiTempLabel(NULL);
4098     pic16_emitcode("pop","acc");   
4099     /* if there was an over flow we don't 
4100     adjust the sign of the result */
4101     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4102     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4103     CLRC ;
4104     pic16_emitcode("clr","a");
4105     pic16_emitcode("subb","a,b");
4106     pic16_emitcode("mov","b,a");
4107     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4108
4109     /* now we are done */
4110     pic16_aopPut(AOP(result),"b",0);
4111
4112 }
4113
4114 /*-----------------------------------------------------------------*/
4115 /* genMod - generates code for division                            */
4116 /*-----------------------------------------------------------------*/
4117 static void genMod (iCode *ic)
4118 {
4119     operand *left = IC_LEFT(ic);
4120     operand *right = IC_RIGHT(ic);
4121     operand *result= IC_RESULT(ic);  
4122
4123     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4124     /* assign the amsops */
4125     pic16_aopOp (left,ic,FALSE);
4126     pic16_aopOp (right,ic,FALSE);
4127     pic16_aopOp (result,ic,TRUE);
4128
4129     /* special cases first */
4130     /* both are bits */
4131     if (AOP_TYPE(left) == AOP_CRY &&
4132         AOP_TYPE(right)== AOP_CRY) {
4133         genModbits(left,right,result);
4134         goto release ;
4135     }
4136
4137     /* if both are of size == 1 */
4138     if (AOP_SIZE(left) == 1 &&
4139         AOP_SIZE(right) == 1 ) {
4140         genModOneByte(left,right,result);
4141         goto release ;
4142     }
4143
4144     /* should have been converted to function call */
4145     assert(0);
4146
4147 release :
4148     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4149     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4150     pic16_freeAsmop(result,NULL,ic,TRUE); 
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genIfxJump :- will create a jump depending on the ifx           */
4155 /*-----------------------------------------------------------------*/
4156 /*
4157   note: May need to add parameter to indicate when a variable is in bit space.
4158 */
4159 static void genIfxJump (iCode *ic, char *jval)
4160 {
4161
4162     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4163     /* if true label then we jump if condition
4164     supplied is true */
4165     if ( IC_TRUE(ic) ) {
4166
4167         if(strcmp(jval,"a") == 0)
4168           emitSKPZ;
4169         else if (strcmp(jval,"c") == 0)
4170           emitSKPC;
4171         else {
4172           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4173           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4174         }
4175
4176         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4177         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4178
4179     }
4180     else {
4181         /* false label is present */
4182         if(strcmp(jval,"a") == 0)
4183           emitSKPNZ;
4184         else if (strcmp(jval,"c") == 0)
4185           emitSKPNC;
4186         else {
4187           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4188           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4189         }
4190
4191         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4192         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4193
4194     }
4195
4196
4197     /* mark the icode as generated */
4198     ic->generated = 1;
4199 }
4200
4201 /*-----------------------------------------------------------------*/
4202 /* genSkip                                                         */
4203 /*-----------------------------------------------------------------*/
4204 static void genSkip(iCode *ifx,int status_bit)
4205 {
4206   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4207   if(!ifx)
4208     return;
4209
4210   if ( IC_TRUE(ifx) ) {
4211     switch(status_bit) {
4212     case 'z':
4213       emitSKPNZ;
4214       break;
4215
4216     case 'c':
4217       emitSKPNC;
4218       break;
4219
4220     case 'd':
4221       emitSKPDC;
4222       break;
4223
4224     }
4225
4226     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4227     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4228
4229   } else {
4230
4231     switch(status_bit) {
4232
4233     case 'z':
4234       emitSKPZ;
4235       break;
4236
4237     case 'c':
4238       emitSKPC;
4239       break;
4240
4241     case 'd':
4242       emitSKPDC;
4243       break;
4244     }
4245     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4246     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4247
4248   }
4249
4250 }
4251
4252 /*-----------------------------------------------------------------*/
4253 /* genSkipc                                                        */
4254 /*-----------------------------------------------------------------*/
4255 static void genSkipc(resolvedIfx *rifx)
4256 {
4257   if(!rifx)
4258     return;
4259
4260   if(rifx->condition)
4261     emitSKPC;
4262   else
4263     emitSKPNC;
4264
4265   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4266   rifx->generated = 1;
4267 }
4268
4269 /*-----------------------------------------------------------------*/
4270 /* genSkipz2                                                       */
4271 /*-----------------------------------------------------------------*/
4272 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4273 {
4274   if(!rifx)
4275     return;
4276
4277   if( (rifx->condition ^ invert_condition) & 1)
4278     emitSKPZ;
4279   else
4280     emitSKPNZ;
4281
4282   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4283   rifx->generated = 1;
4284 }
4285
4286 #if 0
4287 /*-----------------------------------------------------------------*/
4288 /* genSkipz                                                        */
4289 /*-----------------------------------------------------------------*/
4290 static void genSkipz(iCode *ifx, int condition)
4291 {
4292   if(!ifx)
4293     return;
4294
4295   if(condition)
4296     emitSKPNZ;
4297   else
4298     emitSKPZ;
4299
4300   if ( IC_TRUE(ifx) )
4301     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4302   else
4303     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4304
4305   if ( IC_TRUE(ifx) )
4306     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4307   else
4308     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4309
4310 }
4311 #endif
4312
4313 /*-----------------------------------------------------------------*/
4314 /* genSkipCond                                                     */
4315 /*-----------------------------------------------------------------*/
4316 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4317 {
4318   if(!rifx)
4319     return;
4320
4321   if(rifx->condition)
4322     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4323   else
4324     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4325
4326
4327   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4328   rifx->generated = 1;
4329 }
4330
4331 #if 0
4332 /*-----------------------------------------------------------------*/
4333 /* genChkZeroes :- greater or less than comparison                 */
4334 /*     For each byte in a literal that is zero, inclusive or the   */
4335 /*     the corresponding byte in the operand with W                */
4336 /*     returns true if any of the bytes are zero                   */
4337 /*-----------------------------------------------------------------*/
4338 static int genChkZeroes(operand *op, int lit,  int size)
4339 {
4340
4341   int i;
4342   int flag =1;
4343
4344   while(size--) {
4345     i = (lit >> (size*8)) & 0xff;
4346
4347     if(i==0) {
4348       if(flag) 
4349         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4350       else
4351         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4352       flag = 0;
4353     }
4354   }
4355
4356   return (flag==0);
4357 }
4358 #endif
4359
4360 /*-----------------------------------------------------------------*/
4361 /* genCmp :- greater or less than comparison                       */
4362 /*-----------------------------------------------------------------*/
4363 static void genCmp (operand *left,operand *right,
4364                     operand *result, iCode *ifx, int sign)
4365 {
4366   int size; //, offset = 0 ;
4367   unsigned long lit = 0L,i = 0;
4368   resolvedIfx rFalseIfx;
4369   //  resolvedIfx rTrueIfx;
4370   symbol *truelbl;
4371   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4372 /*
4373   if(ifx) {
4374     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4375     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4376   }
4377 */
4378
4379   resolveIfx(&rFalseIfx,ifx);
4380   truelbl  = newiTempLabel(NULL);
4381   size = max(AOP_SIZE(left),AOP_SIZE(right));
4382
4383   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4384
4385 #define _swapp
4386
4387   /* if literal is on the right then swap with left */
4388   if ((AOP_TYPE(right) == AOP_LIT)) {
4389     operand *tmp = right ;
4390     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4391     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4392 #ifdef _swapp
4393
4394     lit = (lit - 1) & mask;
4395     right = left;
4396     left = tmp;
4397     rFalseIfx.condition ^= 1;
4398 #endif
4399
4400   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4401     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4402   }
4403
4404
4405   //if(IC_TRUE(ifx) == NULL)
4406   /* if left & right are bit variables */
4407   if (AOP_TYPE(left) == AOP_CRY &&
4408       AOP_TYPE(right) == AOP_CRY ) {
4409     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4410     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4411   } else {
4412     /* subtract right from left if at the
4413        end the carry flag is set then we know that
4414        left is greater than right */
4415
4416     //    {
4417
4418     symbol *lbl  = newiTempLabel(NULL);
4419
4420 #ifndef _swapp
4421     if(AOP_TYPE(right) == AOP_LIT) {
4422
4423       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4424
4425       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4426
4427       /* special cases */
4428
4429       if(lit == 0) {
4430
4431         if(sign != 0) 
4432           genSkipCond(&rFalseIfx,left,size-1,7);
4433         else 
4434           /* no need to compare to 0...*/
4435           /* NOTE: this is a de-generate compare that most certainly 
4436            *       creates some dead code. */
4437           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4438
4439         if(ifx) ifx->generated = 1;
4440         return;
4441
4442       }
4443       size--;
4444
4445       if(size == 0) {
4446         //i = (lit >> (size*8)) & 0xff;
4447         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4448         
4449         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4450
4451         i = ((0-lit) & 0xff);
4452         if(sign) {
4453           if( i == 0x81) { 
4454             /* lit is 0x7f, all signed chars are less than
4455              * this except for 0x7f itself */
4456             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4457             genSkipz2(&rFalseIfx,0);
4458           } else {
4459             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4460             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4461             genSkipc(&rFalseIfx);
4462           }
4463
4464         } else {
4465           if(lit == 1) {
4466             genSkipz2(&rFalseIfx,1);
4467           } else {
4468             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4469             genSkipc(&rFalseIfx);
4470           }
4471         }
4472
4473         if(ifx) ifx->generated = 1;
4474         return;
4475       }
4476
4477       /* chars are out of the way. now do ints and longs */
4478
4479
4480       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4481         
4482       /* special cases */
4483
4484       if(sign) {
4485
4486         if(lit == 0) {
4487           genSkipCond(&rFalseIfx,left,size,7);
4488           if(ifx) ifx->generated = 1;
4489           return;
4490         }
4491
4492         if(lit <0x100) {
4493           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4494
4495           //rFalseIfx.condition ^= 1;
4496           //genSkipCond(&rFalseIfx,left,size,7);
4497           //rFalseIfx.condition ^= 1;
4498
4499           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4500           if(rFalseIfx.condition)
4501             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4502           else
4503             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4504
4505           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4506           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4507           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4508
4509           while(size > 1)
4510             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4511
4512           if(rFalseIfx.condition) {
4513             emitSKPZ;
4514             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4515
4516           } else {
4517             emitSKPNZ;
4518           }
4519
4520           genSkipc(&rFalseIfx);
4521           pic16_emitpLabel(truelbl->key);
4522           if(ifx) ifx->generated = 1;
4523           return;
4524
4525         }
4526
4527         if(size == 1) {
4528
4529           if( (lit & 0xff) == 0) {
4530             /* lower byte is zero */
4531             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4532             i = ((lit >> 8) & 0xff) ^0x80;
4533             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4534             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4535             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4536             genSkipc(&rFalseIfx);
4537
4538
4539             if(ifx) ifx->generated = 1;
4540             return;
4541
4542           }
4543         } else {
4544           /* Special cases for signed longs */
4545           if( (lit & 0xffffff) == 0) {
4546             /* lower byte is zero */
4547             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4548             i = ((lit >> 8*3) & 0xff) ^0x80;
4549             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4550             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4551             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4552             genSkipc(&rFalseIfx);
4553
4554
4555             if(ifx) ifx->generated = 1;
4556             return;
4557
4558           }
4559
4560         }
4561
4562
4563         if(lit & (0x80 << (size*8))) {
4564           /* lit is negative */
4565           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4566
4567           //genSkipCond(&rFalseIfx,left,size,7);
4568
4569           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4570
4571           if(rFalseIfx.condition)
4572             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4573           else
4574             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4575
4576
4577         } else {
4578           /* lit is positive */
4579           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4580           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4581           if(rFalseIfx.condition)
4582             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4583           else
4584             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4585
4586         }
4587
4588         /*
4589           This works, but is only good for ints.
4590           It also requires a "known zero" register.
4591           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4592           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4593           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4594           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4595           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4596           genSkipc(&rFalseIfx);
4597
4598           pic16_emitpLabel(truelbl->key);
4599           if(ifx) ifx->generated = 1;
4600           return;
4601         **/
4602           
4603         /* There are no more special cases, so perform a general compare */
4604   
4605         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4606         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4607
4608         while(size--) {
4609
4610           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4611           emitSKPNZ;
4612           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4613         }
4614         //rFalseIfx.condition ^= 1;
4615         genSkipc(&rFalseIfx);
4616
4617         pic16_emitpLabel(truelbl->key);
4618
4619         if(ifx) ifx->generated = 1;
4620         return;
4621
4622
4623       }
4624
4625
4626       /* sign is out of the way. So now do an unsigned compare */
4627       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4628
4629
4630       /* General case - compare to an unsigned literal on the right.*/
4631
4632       i = (lit >> (size*8)) & 0xff;
4633       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4634       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4635       while(size--) {
4636         i = (lit >> (size*8)) & 0xff;
4637
4638         if(i) {
4639           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4640           emitSKPNZ;
4641           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4642         } else {
4643           /* this byte of the lit is zero, 
4644            *if it's not the last then OR in the variable */
4645           if(size)
4646             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4647         }
4648       }
4649
4650
4651       pic16_emitpLabel(lbl->key);
4652       //if(emitFinalCheck)
4653       genSkipc(&rFalseIfx);
4654       if(sign)
4655         pic16_emitpLabel(truelbl->key);
4656
4657       if(ifx) ifx->generated = 1;
4658       return;
4659
4660
4661     }
4662 #endif  // _swapp
4663
4664     if(AOP_TYPE(left) == AOP_LIT) {
4665       //symbol *lbl = newiTempLabel(NULL);
4666
4667       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4668
4669
4670       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4671
4672       /* Special cases */
4673       if((lit == 0) && (sign == 0)){
4674
4675         size--;
4676         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4677         while(size) 
4678           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4679
4680         genSkipz2(&rFalseIfx,0);
4681         if(ifx) ifx->generated = 1;
4682         return;
4683       }
4684
4685       if(size==1) {
4686         /* Special cases */
4687         lit &= 0xff;
4688         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4689           /* degenerate compare can never be true */
4690           if(rFalseIfx.condition == 0)
4691             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4692
4693           if(ifx) ifx->generated = 1;
4694           return;
4695         }
4696
4697         if(sign) {
4698           /* signed comparisons to a literal byte */
4699
4700           int lp1 = (lit+1) & 0xff;
4701
4702           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4703           switch (lp1) {
4704           case 0:
4705             rFalseIfx.condition ^= 1;
4706             genSkipCond(&rFalseIfx,right,0,7);
4707             break;
4708           case 0x7f:
4709             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4710             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4711             genSkipz2(&rFalseIfx,1);
4712             break;
4713           default:
4714             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4715             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4716             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4717             rFalseIfx.condition ^= 1;
4718             genSkipc(&rFalseIfx);
4719             break;
4720           }
4721         } else {
4722           /* unsigned comparisons to a literal byte */
4723
4724           switch(lit & 0xff ) {
4725           case 0:
4726             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4727             genSkipz2(&rFalseIfx,0);
4728             break;
4729           case 0x7f:
4730             rFalseIfx.condition ^= 1;
4731             genSkipCond(&rFalseIfx,right,0,7);
4732             break;
4733
4734           default:
4735             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4736             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4737             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4738             rFalseIfx.condition ^= 1;
4739             if (AOP_TYPE(result) == AOP_CRY)
4740               genSkipc(&rFalseIfx);
4741             else {
4742               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4743               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4744             }         
4745             break;
4746           }
4747         }
4748
4749         if(ifx) ifx->generated = 1;
4750         //goto check_carry;
4751         return;
4752
4753       } else {
4754
4755         /* Size is greater than 1 */
4756
4757         if(sign) {
4758           int lp1 = lit+1;
4759
4760           size--;
4761
4762           if(lp1 == 0) {
4763             /* this means lit = 0xffffffff, or -1 */
4764
4765
4766             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4767             rFalseIfx.condition ^= 1;
4768             genSkipCond(&rFalseIfx,right,size,7);
4769             if(ifx) ifx->generated = 1;
4770             return;
4771           }
4772
4773           if(lit == 0) {
4774             int s = size;
4775
4776             if(rFalseIfx.condition) {
4777               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4778               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4779             }
4780
4781             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4782             while(size--)
4783               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4784
4785
4786             emitSKPZ;
4787             if(rFalseIfx.condition) {
4788               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4789               pic16_emitpLabel(truelbl->key);
4790             }else {
4791               rFalseIfx.condition ^= 1;
4792               genSkipCond(&rFalseIfx,right,s,7);
4793             }
4794
4795             if(ifx) ifx->generated = 1;
4796             return;
4797           }
4798
4799           if((size == 1) &&  (0 == (lp1&0xff))) {
4800             /* lower byte of signed word is zero */
4801             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4802             i = ((lp1 >> 8) & 0xff) ^0x80;
4803             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4804             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4805             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4806             rFalseIfx.condition ^= 1;
4807             genSkipc(&rFalseIfx);
4808
4809
4810             if(ifx) ifx->generated = 1;
4811             return;
4812           }
4813
4814           if(lit & (0x80 << (size*8))) {
4815             /* Lit is less than zero */
4816             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4817             //rFalseIfx.condition ^= 1;
4818             //genSkipCond(&rFalseIfx,left,size,7);
4819             //rFalseIfx.condition ^= 1;
4820             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4821             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4822
4823             if(rFalseIfx.condition)
4824               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4825             else
4826               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4827
4828
4829           } else {
4830             /* Lit is greater than or equal to zero */
4831             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4832             //rFalseIfx.condition ^= 1;
4833             //genSkipCond(&rFalseIfx,right,size,7);
4834             //rFalseIfx.condition ^= 1;
4835
4836             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4837             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4838
4839             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4840             if(rFalseIfx.condition)
4841               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4842             else
4843               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4844
4845           }
4846
4847
4848           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4849           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4850
4851           while(size--) {
4852
4853             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4854             emitSKPNZ;
4855             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4856           }
4857           rFalseIfx.condition ^= 1;
4858           //rFalseIfx.condition = 1;
4859           genSkipc(&rFalseIfx);
4860
4861           pic16_emitpLabel(truelbl->key);
4862
4863           if(ifx) ifx->generated = 1;
4864           return;
4865           // end of if (sign)
4866         } else {
4867
4868           /* compare word or long to an unsigned literal on the right.*/
4869
4870
4871           size--;
4872           if(lit < 0xff) {
4873             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4874             switch (lit) {
4875             case 0:
4876               break; /* handled above */
4877 /*
4878             case 0xff:
4879               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4880               while(size--)
4881                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4882               genSkipz2(&rFalseIfx,0);
4883               break;
4884 */
4885             default:
4886               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4887               while(--size)
4888                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4889
4890               emitSKPZ;
4891               if(rFalseIfx.condition)
4892                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4893               else
4894                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4895
4896
4897               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4898               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4899
4900               rFalseIfx.condition ^= 1;
4901               genSkipc(&rFalseIfx);
4902             }
4903
4904             pic16_emitpLabel(truelbl->key);
4905
4906             if(ifx) ifx->generated = 1;
4907             return;
4908           }
4909
4910
4911           lit++;
4912           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4913           i = (lit >> (size*8)) & 0xff;
4914
4915           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4916           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4917
4918           while(size--) {
4919             i = (lit >> (size*8)) & 0xff;
4920
4921             if(i) {
4922               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4923               emitSKPNZ;
4924               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4925             } else {
4926               /* this byte of the lit is zero, 
4927                *if it's not the last then OR in the variable */
4928               if(size)
4929                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4930             }
4931           }
4932
4933
4934           pic16_emitpLabel(lbl->key);
4935
4936           rFalseIfx.condition ^= 1;
4937           genSkipc(&rFalseIfx);
4938         }
4939
4940         if(sign)
4941           pic16_emitpLabel(truelbl->key);
4942         if(ifx) ifx->generated = 1;
4943         return;
4944       }
4945     }
4946     /* Compare two variables */
4947
4948     DEBUGpic16_emitcode(";sign","%d",sign);
4949
4950     size--;
4951     if(sign) {
4952       /* Sigh. thus sucks... */
4953       if(size) {
4954         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4955         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4956         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4957         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4958         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4959         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4960       } else {
4961         /* Signed char comparison */
4962         /* Special thanks to Nikolai Golovchenko for this snippet */
4963         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4964         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4965         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4966         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4967         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4968         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4969
4970         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4971         genSkipc(&rFalseIfx);
4972           
4973         if(ifx) ifx->generated = 1;
4974         return;
4975       }
4976
4977     } else {
4978
4979       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4980       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4981     }
4982
4983
4984     /* The rest of the bytes of a multi-byte compare */
4985     while (size) {
4986
4987       emitSKPZ;
4988       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4989       size--;
4990
4991       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4992       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4993
4994
4995     }
4996
4997     pic16_emitpLabel(lbl->key);
4998
4999     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5000     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5001         (AOP_TYPE(result) == AOP_REG)) {
5002       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5003       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5004     } else {
5005       genSkipc(&rFalseIfx);
5006     }         
5007     //genSkipc(&rFalseIfx);
5008     if(ifx) ifx->generated = 1;
5009
5010     return;
5011
5012   }
5013
5014   // check_carry:
5015   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5016     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5017     pic16_outBitC(result);
5018   } else {
5019     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5020     /* if the result is used in the next
5021        ifx conditional branch then generate
5022        code a little differently */
5023     if (ifx )
5024       genIfxJump (ifx,"c");
5025     else
5026       pic16_outBitC(result);
5027     /* leave the result in acc */
5028   }
5029
5030 }
5031
5032 /*-----------------------------------------------------------------*/
5033 /* genCmpGt :- greater than comparison                             */
5034 /*-----------------------------------------------------------------*/
5035 static void genCmpGt (iCode *ic, iCode *ifx)
5036 {
5037     operand *left, *right, *result;
5038     sym_link *letype , *retype;
5039     int sign ;
5040
5041     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5042     left = IC_LEFT(ic);
5043     right= IC_RIGHT(ic);
5044     result = IC_RESULT(ic);
5045
5046     letype = getSpec(operandType(left));
5047     retype =getSpec(operandType(right));
5048     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5049     /* assign the amsops */
5050     pic16_aopOp (left,ic,FALSE);
5051     pic16_aopOp (right,ic,FALSE);
5052     pic16_aopOp (result,ic,TRUE);
5053
5054     genCmp(right, left, result, ifx, sign);
5055
5056     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5057     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5058     pic16_freeAsmop(result,NULL,ic,TRUE); 
5059 }
5060
5061 /*-----------------------------------------------------------------*/
5062 /* genCmpLt - less than comparisons                                */
5063 /*-----------------------------------------------------------------*/
5064 static void genCmpLt (iCode *ic, iCode *ifx)
5065 {
5066     operand *left, *right, *result;
5067     sym_link *letype , *retype;
5068     int sign ;
5069
5070     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5071     left = IC_LEFT(ic);
5072     right= IC_RIGHT(ic);
5073     result = IC_RESULT(ic);
5074
5075     letype = getSpec(operandType(left));
5076     retype =getSpec(operandType(right));
5077     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5078
5079     /* assign the amsops */
5080     pic16_aopOp (left,ic,FALSE);
5081     pic16_aopOp (right,ic,FALSE);
5082     pic16_aopOp (result,ic,TRUE);
5083
5084     genCmp(left, right, result, ifx, sign);
5085
5086     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5087     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5088     pic16_freeAsmop(result,NULL,ic,TRUE); 
5089 }
5090
5091 /*-----------------------------------------------------------------*/
5092 /* genc16bit2lit - compare a 16 bit value to a literal             */
5093 /*-----------------------------------------------------------------*/
5094 static void genc16bit2lit(operand *op, int lit, int offset)
5095 {
5096   int i;
5097
5098   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5099   if( (lit&0xff) == 0) 
5100     i=1;
5101   else
5102     i=0;
5103
5104   switch( BYTEofLONG(lit,i)) { 
5105   case 0:
5106     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5107     break;
5108   case 1:
5109     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5110     break;
5111   case 0xff:
5112     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5113     break;
5114   default:
5115     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5116     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5117   }
5118
5119   i ^= 1;
5120
5121   switch( BYTEofLONG(lit,i)) { 
5122   case 0:
5123     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5124     break;
5125   case 1:
5126     emitSKPNZ;
5127     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5128     break;
5129   case 0xff:
5130     emitSKPNZ;
5131     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5132     break;
5133   default:
5134     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5135     emitSKPNZ;
5136     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5137
5138   }
5139
5140 }
5141
5142 /*-----------------------------------------------------------------*/
5143 /* gencjneshort - compare and jump if not equal                    */
5144 /*-----------------------------------------------------------------*/
5145 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5146 {
5147   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5148   int offset = 0;
5149   int res_offset = 0;  /* the result may be a different size then left or right */
5150   int res_size = AOP_SIZE(result);
5151   resolvedIfx rIfx;
5152   symbol *lbl, *lbl_done;
5153
5154   unsigned long lit = 0L;
5155   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5156
5157   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5158   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5159   if(result)
5160     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5161   resolveIfx(&rIfx,ifx);
5162   lbl =  newiTempLabel(NULL);
5163   lbl_done =  newiTempLabel(NULL);
5164
5165
5166   /* if the left side is a literal or 
5167      if the right is in a pointer register and left 
5168      is not */
5169   if ((AOP_TYPE(left) == AOP_LIT) || 
5170       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5171     operand *t = right;
5172     right = left;
5173     left = t;
5174   }
5175   if(AOP_TYPE(right) == AOP_LIT)
5176     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5177
5178   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5179     preserve_result = 1;
5180
5181   if(result && !preserve_result)
5182     {
5183       int i;
5184       for(i = 0; i < AOP_SIZE(result); i++)
5185         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5186     }
5187
5188
5189   /* if the right side is a literal then anything goes */
5190   if (AOP_TYPE(right) == AOP_LIT &&
5191       AOP_TYPE(left) != AOP_DIR ) {
5192     switch(size) {
5193     case 2:
5194       genc16bit2lit(left, lit, 0);
5195       emitSKPZ;
5196       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5197       break;
5198     default:
5199       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5200       while (size--) {
5201         if(lit & 0xff) {
5202           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5203           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5204         } else {
5205           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5206         }
5207
5208         emitSKPZ;
5209         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5210         offset++;
5211         if(res_offset < res_size-1)
5212           res_offset++;
5213         lit >>= 8;
5214       }
5215       break;
5216     }
5217   }
5218
5219   /* if the right side is in a register or in direct space or
5220      if the left is a pointer register & right is not */    
5221   else if (AOP_TYPE(right) == AOP_REG ||
5222            AOP_TYPE(right) == AOP_DIR || 
5223            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5224            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5225     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5226     int lbl_key = lbl->key;
5227
5228     if(result) {
5229       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5230       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5231     }else {
5232       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5233       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5234               __FUNCTION__,__LINE__);
5235       return;
5236     }
5237    
5238 /*     switch(size) { */
5239 /*     case 2: */
5240 /*       genc16bit2lit(left, lit, 0); */
5241 /*       emitSKPNZ; */
5242 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5243 /*       break; */
5244 /*     default: */
5245     while (size--) {
5246       int emit_skip=1;
5247       if((AOP_TYPE(left) == AOP_DIR) && 
5248          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5249
5250         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5251         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5252
5253       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5254             
5255         switch (lit & 0xff) {
5256         case 0:
5257           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5258           break;
5259         case 1:
5260           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5261           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5262           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5263           emit_skip=0;
5264           break;
5265         case 0xff:
5266           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5267           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5268           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5269           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5270           emit_skip=0;
5271           break;
5272         default:
5273           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5274           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5275         }
5276         lit >>= 8;
5277
5278       } else {
5279         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5280       }
5281       if(emit_skip) {
5282         if(AOP_TYPE(result) == AOP_CRY) {
5283           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5284           if(rIfx.condition)
5285             emitSKPNZ;
5286           else
5287             emitSKPZ;
5288           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5289         } else {
5290           /* fix me. probably need to check result size too */
5291           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5292           if(rIfx.condition)
5293             emitSKPZ;
5294           else
5295             emitSKPNZ;
5296           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5297           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5298         }
5299         if(ifx)
5300           ifx->generated=1;
5301       }
5302       emit_skip++;
5303       offset++;
5304       if(res_offset < res_size-1)
5305         res_offset++;
5306     }
5307 /*       break; */
5308 /*     } */
5309   } else if(AOP_TYPE(right) == AOP_REG &&
5310             AOP_TYPE(left) != AOP_DIR){
5311
5312     while(size--) {
5313       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5314       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5315       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5316       if(rIfx.condition)
5317         emitSKPNZ;
5318       else
5319         emitSKPZ;
5320       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5321       offset++;
5322       if(res_offset < res_size-1)
5323         res_offset++;
5324     }
5325       
5326   }else{
5327     /* right is a pointer reg need both a & b */
5328     while(size--) {
5329       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5330       if(strcmp(l,"b"))
5331         pic16_emitcode("mov","b,%s",l);
5332       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5333       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5334       offset++;
5335     }
5336   }
5337
5338   if(result && preserve_result)
5339     {
5340       int i;
5341       for(i = 0; i < AOP_SIZE(result); i++)
5342         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5343     }
5344
5345   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5346
5347   if(result && preserve_result)
5348     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5349
5350   if(!rIfx.condition)
5351     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5352
5353   pic16_emitpLabel(lbl->key);
5354
5355   if(result && preserve_result)
5356     {
5357       int i;
5358       for(i = 0; i < AOP_SIZE(result); i++)
5359         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5360
5361       pic16_emitpLabel(lbl_done->key);
5362    }
5363
5364   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5365
5366   if(ifx)
5367     ifx->generated = 1;
5368 }
5369
5370 #if 0
5371 /*-----------------------------------------------------------------*/
5372 /* gencjne - compare and jump if not equal                         */
5373 /*-----------------------------------------------------------------*/
5374 static void gencjne(operand *left, operand *right, iCode *ifx)
5375 {
5376     symbol *tlbl  = newiTempLabel(NULL);
5377
5378     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5379     gencjneshort(left, right, lbl);
5380
5381     pic16_emitcode("mov","a,%s",one);
5382     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5383     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5384     pic16_emitcode("clr","a");
5385     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5386
5387     pic16_emitpLabel(lbl->key);
5388     pic16_emitpLabel(tlbl->key);
5389
5390 }
5391 #endif
5392
5393 /*-----------------------------------------------------------------*/
5394 /* genCmpEq - generates code for equal to                          */
5395 /*-----------------------------------------------------------------*/
5396 static void genCmpEq (iCode *ic, iCode *ifx)
5397 {
5398     operand *left, *right, *result;
5399     unsigned long lit = 0L;
5400     int size,offset=0;
5401     symbol *falselbl  = newiTempLabel(NULL);
5402
5403
5404     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5405
5406     if(ifx)
5407       DEBUGpic16_emitcode ("; ifx is non-null","");
5408     else
5409       DEBUGpic16_emitcode ("; ifx is null","");
5410
5411     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5412     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5413     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5414
5415     size = max(AOP_SIZE(left),AOP_SIZE(right));
5416
5417     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5418
5419     /* if literal, literal on the right or 
5420     if the right is in a pointer register and left 
5421     is not */
5422     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5423         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5424       operand *tmp = right ;
5425       right = left;
5426       left = tmp;
5427     }
5428
5429
5430     if(ifx && !AOP_SIZE(result)){
5431         symbol *tlbl;
5432         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5433         /* if they are both bit variables */
5434         if (AOP_TYPE(left) == AOP_CRY &&
5435             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5436                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5437             if(AOP_TYPE(right) == AOP_LIT){
5438                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5439                 if(lit == 0L){
5440                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5441                     pic16_emitcode("cpl","c");
5442                 } else if(lit == 1L) {
5443                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5444                 } else {
5445                     pic16_emitcode("clr","c");
5446                 }
5447                 /* AOP_TYPE(right) == AOP_CRY */
5448             } else {
5449                 symbol *lbl = newiTempLabel(NULL);
5450                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5451                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5452                 pic16_emitcode("cpl","c");
5453                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5454             }
5455             /* if true label then we jump if condition
5456             supplied is true */
5457             tlbl = newiTempLabel(NULL);
5458             if ( IC_TRUE(ifx) ) {
5459                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5460                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5461             } else {
5462                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5463                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5464             }
5465             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5466
5467                 {
5468                 /* left and right are both bit variables, result is carry */
5469                         resolvedIfx rIfx;
5470               
5471                         resolveIfx(&rIfx,ifx);
5472
5473                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5474                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5475                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5476                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5477                         genSkipz2(&rIfx,0);
5478                 }
5479         } else {
5480
5481                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5482
5483                         /* They're not both bit variables. Is the right a literal? */
5484                         if(AOP_TYPE(right) == AOP_LIT) {
5485                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5486             
5487                         switch(size) {
5488
5489                                 case 1:
5490                                         switch(lit & 0xff) {
5491                                                 case 1:
5492                                                                 if ( IC_TRUE(ifx) ) {
5493                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5494                                                                         emitSKPNZ;
5495                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5496                                                                 } else {
5497                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5498                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5499                                                                 }
5500                                                                 break;
5501                                                 case 0xff:
5502                                                                 if ( IC_TRUE(ifx) ) {
5503                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5504                                                                         emitSKPNZ;
5505                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5506                                                                 } else {
5507                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5508                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5509                                                                 }
5510                                                                 break;
5511                                                 default:
5512                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5513                                                                 if(lit)
5514                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5515                                                                 genSkip(ifx,'z');
5516                                         } // switch lit
5517
5518
5519                                         /* end of size == 1 */
5520                                         break;
5521               
5522                                 case 2:
5523                                         genc16bit2lit(left,lit,offset);
5524                                         genSkip(ifx,'z');
5525                                         break;
5526                                         /* end of size == 2 */
5527
5528                                 default:
5529                                         /* size is 4 */
5530                                         if(lit==0) {
5531                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5532                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5533                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5534                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5535                                                 genSkip(ifx,'z');
5536                                         } else {
5537                                                 /* search for patterns that can be optimized */
5538
5539                                                 genc16bit2lit(left,lit,0);
5540                                                 lit >>= 16;
5541                                                 if(lit) {
5542                                                                 if(IC_TRUE(ifx))
5543                                                                 emitSKPZ; // if hi word unequal
5544                                                                 else
5545                                                                 emitSKPNZ; // if hi word equal
5546                                                                 // fail early
5547                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5548                                                         genc16bit2lit(left,lit,2);
5549                                                         genSkip(ifx,'z');
5550                                                 } else {
5551                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5552                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5553                                                         genSkip(ifx,'z');
5554                                                 }
5555                                         }
5556                                                 pic16_emitpLabel(falselbl->key);
5557                                                 break;
5558
5559                         } // switch size
5560           
5561                         ifx->generated = 1;
5562                         goto release ;
5563             
5564
5565           } else if(AOP_TYPE(right) == AOP_CRY ) {
5566             /* we know the left is not a bit, but that the right is */
5567             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5568             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5569                       pic16_popGet(AOP(right),offset));
5570             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5571
5572             /* if the two are equal, then W will be 0 and the Z bit is set
5573              * we could test Z now, or go ahead and check the high order bytes if
5574              * the variable we're comparing is larger than a byte. */
5575
5576             while(--size)
5577               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5578
5579             if ( IC_TRUE(ifx) ) {
5580               emitSKPNZ;
5581               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5582               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5583             } else {
5584               emitSKPZ;
5585               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5586               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5587             }
5588
5589           } else {
5590             /* They're both variables that are larger than bits */
5591             int s = size;
5592
5593             tlbl = newiTempLabel(NULL);
5594
5595             while(size--) {
5596               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5597               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5598
5599               if ( IC_TRUE(ifx) ) {
5600                 if(size) {
5601                   emitSKPZ;
5602                 
5603                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5604
5605                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5606                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5607                 } else {
5608                   emitSKPNZ;
5609
5610                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5611
5612
5613                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5614                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5615                 }
5616               } else {
5617                 emitSKPZ;
5618
5619                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5620
5621                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5622                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5623               }
5624               offset++;
5625             }
5626             if(s>1 && IC_TRUE(ifx)) {
5627               pic16_emitpLabel(tlbl->key);
5628               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5629             }
5630           }
5631         }
5632         /* mark the icode as generated */
5633         ifx->generated = 1;
5634         goto release ;
5635     }
5636
5637     /* if they are both bit variables */
5638     if (AOP_TYPE(left) == AOP_CRY &&
5639         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5640         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5641         if(AOP_TYPE(right) == AOP_LIT){
5642             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5643             if(lit == 0L){
5644                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5645                 pic16_emitcode("cpl","c");
5646             } else if(lit == 1L) {
5647                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5648             } else {
5649                 pic16_emitcode("clr","c");
5650             }
5651             /* AOP_TYPE(right) == AOP_CRY */
5652         } else {
5653             symbol *lbl = newiTempLabel(NULL);
5654             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5655             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5656             pic16_emitcode("cpl","c");
5657             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5658         }
5659         /* c = 1 if egal */
5660         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5661             pic16_outBitC(result);
5662             goto release ;
5663         }
5664         if (ifx) {
5665             genIfxJump (ifx,"c");
5666             goto release ;
5667         }
5668         /* if the result is used in an arithmetic operation
5669         then put the result in place */
5670         pic16_outBitC(result);
5671     } else {
5672       
5673       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5674       gencjne(left,right,result,ifx);
5675 /*
5676       if(ifx) 
5677         gencjne(left,right,newiTempLabel(NULL));
5678       else {
5679         if(IC_TRUE(ifx)->key)
5680           gencjne(left,right,IC_TRUE(ifx)->key);
5681         else
5682           gencjne(left,right,IC_FALSE(ifx)->key);
5683         ifx->generated = 1;
5684         goto release ;
5685       }
5686       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5687         pic16_aopPut(AOP(result),"a",0);
5688         goto release ;
5689       }
5690
5691       if (ifx) {
5692         genIfxJump (ifx,"a");
5693         goto release ;
5694       }
5695 */
5696       /* if the result is used in an arithmetic operation
5697          then put the result in place */
5698 /*
5699       if (AOP_TYPE(result) != AOP_CRY) 
5700         pic16_outAcc(result);
5701 */
5702       /* leave the result in acc */
5703     }
5704
5705 release:
5706     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5707     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5708     pic16_freeAsmop(result,NULL,ic,TRUE);
5709 }
5710
5711 /*-----------------------------------------------------------------*/
5712 /* ifxForOp - returns the icode containing the ifx for operand     */
5713 /*-----------------------------------------------------------------*/
5714 static iCode *ifxForOp ( operand *op, iCode *ic )
5715 {
5716     /* if true symbol then needs to be assigned */
5717     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5718     if (IS_TRUE_SYMOP(op))
5719         return NULL ;
5720
5721     /* if this has register type condition and
5722     the next instruction is ifx with the same operand
5723     and live to of the operand is upto the ifx only then */
5724     if (ic->next &&
5725         ic->next->op == IFX &&
5726         IC_COND(ic->next)->key == op->key &&
5727         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5728         return ic->next;
5729
5730     if (ic->next &&
5731         ic->next->op == IFX &&
5732         IC_COND(ic->next)->key == op->key) {
5733       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5734       return ic->next;
5735     }
5736
5737     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5738     if (ic->next &&
5739         ic->next->op == IFX)
5740       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5741
5742     if (ic->next &&
5743         ic->next->op == IFX &&
5744         IC_COND(ic->next)->key == op->key) {
5745       DEBUGpic16_emitcode ("; "," key is okay");
5746       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5747                            OP_SYMBOL(op)->liveTo,
5748                            ic->next->seq);
5749     }
5750
5751
5752     return NULL;
5753 }
5754 /*-----------------------------------------------------------------*/
5755 /* genAndOp - for && operation                                     */
5756 /*-----------------------------------------------------------------*/
5757 static void genAndOp (iCode *ic)
5758 {
5759     operand *left,*right, *result;
5760 /*     symbol *tlbl; */
5761
5762     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5763     /* note here that && operations that are in an
5764     if statement are taken away by backPatchLabels
5765     only those used in arthmetic operations remain */
5766     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5767     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5768     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5769
5770     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5771
5772     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5773     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5774     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5775
5776     /* if both are bit variables */
5777 /*     if (AOP_TYPE(left) == AOP_CRY && */
5778 /*         AOP_TYPE(right) == AOP_CRY ) { */
5779 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5780 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5781 /*         pic16_outBitC(result); */
5782 /*     } else { */
5783 /*         tlbl = newiTempLabel(NULL); */
5784 /*         pic16_toBoolean(left);     */
5785 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5786 /*         pic16_toBoolean(right); */
5787 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5788 /*         pic16_outBitAcc(result); */
5789 /*     } */
5790
5791     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5792     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5793     pic16_freeAsmop(result,NULL,ic,TRUE);
5794 }
5795
5796
5797 /*-----------------------------------------------------------------*/
5798 /* genOrOp - for || operation                                      */
5799 /*-----------------------------------------------------------------*/
5800 /*
5801   tsd pic port -
5802   modified this code, but it doesn't appear to ever get called
5803 */
5804
5805 static void genOrOp (iCode *ic)
5806 {
5807     operand *left,*right, *result;
5808     symbol *tlbl;
5809
5810     /* note here that || operations that are in an
5811     if statement are taken away by backPatchLabels
5812     only those used in arthmetic operations remain */
5813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5814     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5815     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5816     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5817
5818     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5819
5820     /* if both are bit variables */
5821     if (AOP_TYPE(left) == AOP_CRY &&
5822         AOP_TYPE(right) == AOP_CRY ) {
5823       pic16_emitcode("clrc","");
5824       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5825                AOP(left)->aopu.aop_dir,
5826                AOP(left)->aopu.aop_dir);
5827       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5828                AOP(right)->aopu.aop_dir,
5829                AOP(right)->aopu.aop_dir);
5830       pic16_emitcode("setc","");
5831
5832     } else {
5833         tlbl = newiTempLabel(NULL);
5834         pic16_toBoolean(left);
5835         emitSKPZ;
5836         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5837         pic16_toBoolean(right);
5838         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5839
5840         pic16_outBitAcc(result);
5841     }
5842
5843     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5844     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5845     pic16_freeAsmop(result,NULL,ic,TRUE);            
5846 }
5847
5848 /*-----------------------------------------------------------------*/
5849 /* isLiteralBit - test if lit == 2^n                               */
5850 /*-----------------------------------------------------------------*/
5851 static int isLiteralBit(unsigned long lit)
5852 {
5853     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5854     0x100L,0x200L,0x400L,0x800L,
5855     0x1000L,0x2000L,0x4000L,0x8000L,
5856     0x10000L,0x20000L,0x40000L,0x80000L,
5857     0x100000L,0x200000L,0x400000L,0x800000L,
5858     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5859     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5860     int idx;
5861     
5862     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5863     for(idx = 0; idx < 32; idx++)
5864         if(lit == pw[idx])
5865             return idx+1;
5866     return 0;
5867 }
5868
5869 /*-----------------------------------------------------------------*/
5870 /* continueIfTrue -                                                */
5871 /*-----------------------------------------------------------------*/
5872 static void continueIfTrue (iCode *ic)
5873 {
5874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5875     if(IC_TRUE(ic))
5876         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5877     ic->generated = 1;
5878 }
5879
5880 /*-----------------------------------------------------------------*/
5881 /* jmpIfTrue -                                                     */
5882 /*-----------------------------------------------------------------*/
5883 static void jumpIfTrue (iCode *ic)
5884 {
5885     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5886     if(!IC_TRUE(ic))
5887         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5888     ic->generated = 1;
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* jmpTrueOrFalse -                                                */
5893 /*-----------------------------------------------------------------*/
5894 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5895 {
5896     // ugly but optimized by peephole
5897     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5898     if(IC_TRUE(ic)){
5899         symbol *nlbl = newiTempLabel(NULL);
5900         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5901         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5902         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5903         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5904     }
5905     else{
5906         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5907         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5908     }
5909     ic->generated = 1;
5910 }
5911
5912 /*-----------------------------------------------------------------*/
5913 /* genAnd  - code for and                                          */
5914 /*-----------------------------------------------------------------*/
5915 static void genAnd (iCode *ic, iCode *ifx)
5916 {
5917   operand *left, *right, *result;
5918   int size, offset=0;  
5919   unsigned long lit = 0L;
5920   int bytelit = 0;
5921   resolvedIfx rIfx;
5922
5923
5924   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5925   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5926   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5927   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5928
5929   resolveIfx(&rIfx,ifx);
5930
5931   /* if left is a literal & right is not then exchange them */
5932   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5933       AOP_NEEDSACC(left)) {
5934     operand *tmp = right ;
5935     right = left;
5936     left = tmp;
5937   }
5938
5939   /* if result = right then exchange them */
5940   if(pic16_sameRegs(AOP(result),AOP(right))){
5941     operand *tmp = right ;
5942     right = left;
5943     left = tmp;
5944   }
5945
5946   /* if right is bit then exchange them */
5947   if (AOP_TYPE(right) == AOP_CRY &&
5948       AOP_TYPE(left) != AOP_CRY){
5949     operand *tmp = right ;
5950     right = left;
5951     left = tmp;
5952   }
5953   if(AOP_TYPE(right) == AOP_LIT)
5954     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5955
5956   size = AOP_SIZE(result);
5957
5958   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5959
5960   // if(bit & yy)
5961   // result = bit & yy;
5962   if (AOP_TYPE(left) == AOP_CRY){
5963     // c = bit & literal;
5964     if(AOP_TYPE(right) == AOP_LIT){
5965       if(lit & 1) {
5966         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5967           // no change
5968           goto release;
5969         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5970       } else {
5971         // bit(result) = 0;
5972         if(size && (AOP_TYPE(result) == AOP_CRY)){
5973           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5974           goto release;
5975         }
5976         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5977           jumpIfTrue(ifx);
5978           goto release;
5979         }
5980         pic16_emitcode("clr","c");
5981       }
5982     } else {
5983       if (AOP_TYPE(right) == AOP_CRY){
5984         // c = bit & bit;
5985         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5986         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5987       } else {
5988         // c = bit & val;
5989         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5990         // c = lsb
5991         pic16_emitcode("rrc","a");
5992         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5993       }
5994     }
5995     // bit = c
5996     // val = c
5997     if(size)
5998       pic16_outBitC(result);
5999     // if(bit & ...)
6000     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6001       genIfxJump(ifx, "c");           
6002     goto release ;
6003   }
6004
6005   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6006   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6007   if((AOP_TYPE(right) == AOP_LIT) &&
6008      (AOP_TYPE(result) == AOP_CRY) &&
6009      (AOP_TYPE(left) != AOP_CRY)){
6010     int posbit = isLiteralBit(lit);
6011     /* left &  2^n */
6012     if(posbit){
6013       posbit--;
6014       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6015       // bit = left & 2^n
6016       if(size)
6017         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6018       // if(left &  2^n)
6019       else{
6020         if(ifx){
6021 /*
6022           if(IC_TRUE(ifx)) {
6023             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6024             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6025           } else {
6026             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6027             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6028           }
6029 */
6030           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6031                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6032           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6033           
6034           ifx->generated = 1;
6035         }
6036         goto release;
6037       }
6038     } else {
6039       symbol *tlbl = newiTempLabel(NULL);
6040       int sizel = AOP_SIZE(left);
6041       if(size)
6042         pic16_emitcode("setb","c");
6043       while(sizel--){
6044         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6045           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6046           // byte ==  2^n ?
6047           if((posbit = isLiteralBit(bytelit)) != 0)
6048             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6049           else{
6050             if(bytelit != 0x0FFL)
6051               pic16_emitcode("anl","a,%s",
6052                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6053             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6054           }
6055         }
6056         offset++;
6057       }
6058       // bit = left & literal
6059       if(size){
6060         pic16_emitcode("clr","c");
6061         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6062       }
6063       // if(left & literal)
6064       else{
6065         if(ifx)
6066           jmpTrueOrFalse(ifx, tlbl);
6067         goto release ;
6068       }
6069     }
6070     pic16_outBitC(result);
6071     goto release ;
6072   }
6073
6074   /* if left is same as result */
6075   if(pic16_sameRegs(AOP(result),AOP(left))){
6076     int know_W = -1;
6077     for(;size--; offset++,lit>>=8) {
6078       if(AOP_TYPE(right) == AOP_LIT){
6079         switch(lit & 0xff) {
6080         case 0x00:
6081           /*  and'ing with 0 has clears the result */
6082 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6083           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6084           break;
6085         case 0xff:
6086           /* and'ing with 0xff is a nop when the result and left are the same */
6087           break;
6088
6089         default:
6090           {
6091             int p = my_powof2( (~lit) & 0xff );
6092             if(p>=0) {
6093               /* only one bit is set in the literal, so use a bcf instruction */
6094 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6095               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6096
6097             } else {
6098               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6099               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6100               if(know_W != (lit&0xff))
6101                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6102               know_W = lit &0xff;
6103               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6104             }
6105           }    
6106         }
6107       } else {
6108         if (AOP_TYPE(left) == AOP_ACC) {
6109           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6110         } else {                    
6111           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6112           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6113
6114         }
6115       }
6116     }
6117
6118   } else {
6119     // left & result in different registers
6120     if(AOP_TYPE(result) == AOP_CRY){
6121       // result = bit
6122       // if(size), result in bit
6123       // if(!size && ifx), conditional oper: if(left & right)
6124       symbol *tlbl = newiTempLabel(NULL);
6125       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6126       if(size)
6127         pic16_emitcode("setb","c");
6128       while(sizer--){
6129         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6130         pic16_emitcode("anl","a,%s",
6131                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6132         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6133         offset++;
6134       }
6135       if(size){
6136         CLRC;
6137         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6138         pic16_outBitC(result);
6139       } else if(ifx)
6140         jmpTrueOrFalse(ifx, tlbl);
6141     } else {
6142       for(;(size--);offset++) {
6143         // normal case
6144         // result = left & right
6145         if(AOP_TYPE(right) == AOP_LIT){
6146           int t = (lit >> (offset*8)) & 0x0FFL;
6147           switch(t) { 
6148           case 0x00:
6149             pic16_emitcode("clrf","%s",
6150                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6151             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6152             break;
6153           case 0xff:
6154             pic16_emitcode("movf","%s,w",
6155                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6156             pic16_emitcode("movwf","%s",
6157                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6158             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6159             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6160             break;
6161           default:
6162             pic16_emitcode("movlw","0x%x",t);
6163             pic16_emitcode("andwf","%s,w",
6164                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6165             pic16_emitcode("movwf","%s",
6166                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6167               
6168             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6169             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6170             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6171           }
6172           continue;
6173         }
6174
6175         if (AOP_TYPE(left) == AOP_ACC) {
6176           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6177           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6178         } else {
6179           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6180           pic16_emitcode("andwf","%s,w",
6181                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6182           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6183           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6184         }
6185         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6186         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6187       }
6188     }
6189   }
6190
6191   release :
6192     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6193   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6194   pic16_freeAsmop(result,NULL,ic,TRUE);     
6195 }
6196
6197 /*-----------------------------------------------------------------*/
6198 /* genOr  - code for or                                            */
6199 /*-----------------------------------------------------------------*/
6200 static void genOr (iCode *ic, iCode *ifx)
6201 {
6202     operand *left, *right, *result;
6203     int size, offset=0;
6204     unsigned long lit = 0L;
6205
6206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6207
6208     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6209     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6210     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6211
6212     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6213
6214     /* if left is a literal & right is not then exchange them */
6215     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6216         AOP_NEEDSACC(left)) {
6217         operand *tmp = right ;
6218         right = left;
6219         left = tmp;
6220     }
6221
6222     /* if result = right then exchange them */
6223     if(pic16_sameRegs(AOP(result),AOP(right))){
6224         operand *tmp = right ;
6225         right = left;
6226         left = tmp;
6227     }
6228
6229     /* if right is bit then exchange them */
6230     if (AOP_TYPE(right) == AOP_CRY &&
6231         AOP_TYPE(left) != AOP_CRY){
6232         operand *tmp = right ;
6233         right = left;
6234         left = tmp;
6235     }
6236
6237     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6238
6239     if(AOP_TYPE(right) == AOP_LIT)
6240         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6241
6242     size = AOP_SIZE(result);
6243
6244     // if(bit | yy)
6245     // xx = bit | yy;
6246     if (AOP_TYPE(left) == AOP_CRY){
6247         if(AOP_TYPE(right) == AOP_LIT){
6248             // c = bit & literal;
6249             if(lit){
6250                 // lit != 0 => result = 1
6251                 if(AOP_TYPE(result) == AOP_CRY){
6252                   if(size)
6253                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6254                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6255                   //     AOP(result)->aopu.aop_dir,
6256                   //     AOP(result)->aopu.aop_dir);
6257                     else if(ifx)
6258                         continueIfTrue(ifx);
6259                     goto release;
6260                 }
6261             } else {
6262                 // lit == 0 => result = left
6263                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6264                     goto release;
6265                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6266             }
6267         } else {
6268             if (AOP_TYPE(right) == AOP_CRY){
6269               if(pic16_sameRegs(AOP(result),AOP(left))){
6270                 // c = bit | bit;
6271                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6272                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6273                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6274
6275                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6276                          AOP(result)->aopu.aop_dir,
6277                          AOP(result)->aopu.aop_dir);
6278                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6279                          AOP(right)->aopu.aop_dir,
6280                          AOP(right)->aopu.aop_dir);
6281                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6282                          AOP(result)->aopu.aop_dir,
6283                          AOP(result)->aopu.aop_dir);
6284               } else {
6285                 if( AOP_TYPE(result) == AOP_ACC) {
6286                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6287                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6288                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6289                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6290
6291                 } else {
6292
6293                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6294                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6295                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6296                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6297
6298                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6299                                  AOP(result)->aopu.aop_dir,
6300                                  AOP(result)->aopu.aop_dir);
6301                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6302                                  AOP(right)->aopu.aop_dir,
6303                                  AOP(right)->aopu.aop_dir);
6304                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6305                                  AOP(left)->aopu.aop_dir,
6306                                  AOP(left)->aopu.aop_dir);
6307                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6308                                  AOP(result)->aopu.aop_dir,
6309                                  AOP(result)->aopu.aop_dir);
6310                 }
6311               }
6312             } else {
6313                 // c = bit | val;
6314                 symbol *tlbl = newiTempLabel(NULL);
6315                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6316
6317
6318                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6319                 if( AOP_TYPE(right) == AOP_ACC) {
6320                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6321                   emitSKPNZ;
6322                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6323                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6324                 }
6325
6326
6327
6328                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6329                     pic16_emitcode(";XXX setb","c");
6330                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6331                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6332                 pic16_toBoolean(right);
6333                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6334                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6335                     jmpTrueOrFalse(ifx, tlbl);
6336                     goto release;
6337                 } else {
6338                     CLRC;
6339                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6340                 }
6341             }
6342         }
6343         // bit = c
6344         // val = c
6345         if(size)
6346             pic16_outBitC(result);
6347         // if(bit | ...)
6348         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6349             genIfxJump(ifx, "c");           
6350         goto release ;
6351     }
6352
6353     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6354     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6355     if((AOP_TYPE(right) == AOP_LIT) &&
6356        (AOP_TYPE(result) == AOP_CRY) &&
6357        (AOP_TYPE(left) != AOP_CRY)){
6358         if(lit){
6359           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6360             // result = 1
6361             if(size)
6362                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6363             else 
6364                 continueIfTrue(ifx);
6365             goto release;
6366         } else {
6367           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6368             // lit = 0, result = boolean(left)
6369             if(size)
6370                 pic16_emitcode(";XXX setb","c");
6371             pic16_toBoolean(right);
6372             if(size){
6373                 symbol *tlbl = newiTempLabel(NULL);
6374                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6375                 CLRC;
6376                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6377             } else {
6378                 genIfxJump (ifx,"a");
6379                 goto release;
6380             }
6381         }
6382         pic16_outBitC(result);
6383         goto release ;
6384     }
6385
6386     /* if left is same as result */
6387     if(pic16_sameRegs(AOP(result),AOP(left))){
6388       int know_W = -1;
6389       for(;size--; offset++,lit>>=8) {
6390         if(AOP_TYPE(right) == AOP_LIT){
6391           if((lit & 0xff) == 0)
6392             /*  or'ing with 0 has no effect */
6393             continue;
6394           else {
6395             int p = my_powof2(lit & 0xff);
6396             if(p>=0) {
6397               /* only one bit is set in the literal, so use a bsf instruction */
6398               pic16_emitpcode(POC_BSF,
6399                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6400             } else {
6401               if(know_W != (lit & 0xff))
6402                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6403               know_W = lit & 0xff;
6404               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6405             }
6406                     
6407           }
6408         } else {
6409           if (AOP_TYPE(left) == AOP_ACC) {
6410             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6411             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6412           } else {                  
6413             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6414             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6415
6416             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6417             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6418
6419           }
6420         }
6421       }
6422     } else {
6423         // left & result in different registers
6424         if(AOP_TYPE(result) == AOP_CRY){
6425             // result = bit
6426             // if(size), result in bit
6427             // if(!size && ifx), conditional oper: if(left | right)
6428             symbol *tlbl = newiTempLabel(NULL);
6429             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6430             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6431
6432
6433             if(size)
6434                 pic16_emitcode(";XXX setb","c");
6435             while(sizer--){
6436                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6437                 pic16_emitcode(";XXX orl","a,%s",
6438                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6439                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6440                 offset++;
6441             }
6442             if(size){
6443                 CLRC;
6444                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6445                 pic16_outBitC(result);
6446             } else if(ifx)
6447                 jmpTrueOrFalse(ifx, tlbl);
6448         } else for(;(size--);offset++){
6449           // normal case
6450           // result = left & right
6451           if(AOP_TYPE(right) == AOP_LIT){
6452             int t = (lit >> (offset*8)) & 0x0FFL;
6453             switch(t) { 
6454             case 0x00:
6455               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6456               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6457
6458               pic16_emitcode("movf","%s,w",
6459                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6460               pic16_emitcode("movwf","%s",
6461                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6462               break;
6463             default:
6464               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6465               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6466               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6467
6468               pic16_emitcode("movlw","0x%x",t);
6469               pic16_emitcode("iorwf","%s,w",
6470                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6471               pic16_emitcode("movwf","%s",
6472                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6473               
6474             }
6475             continue;
6476           }
6477
6478           // faster than result <- left, anl result,right
6479           // and better if result is SFR
6480           if (AOP_TYPE(left) == AOP_ACC) {
6481             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6482             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6483           } else {
6484             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6485             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6486
6487             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6488             pic16_emitcode("iorwf","%s,w",
6489                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6490           }
6491           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6492           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6493         }
6494     }
6495
6496 release :
6497     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6498     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6499     pic16_freeAsmop(result,NULL,ic,TRUE);     
6500 }
6501
6502 /*-----------------------------------------------------------------*/
6503 /* genXor - code for xclusive or                                   */
6504 /*-----------------------------------------------------------------*/
6505 static void genXor (iCode *ic, iCode *ifx)
6506 {
6507   operand *left, *right, *result;
6508   int size, offset=0;
6509   unsigned long lit = 0L;
6510
6511   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6512
6513   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6514   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6515   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6516
6517   /* if left is a literal & right is not ||
6518      if left needs acc & right does not */
6519   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6520       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6521     operand *tmp = right ;
6522     right = left;
6523     left = tmp;
6524   }
6525
6526   /* if result = right then exchange them */
6527   if(pic16_sameRegs(AOP(result),AOP(right))){
6528     operand *tmp = right ;
6529     right = left;
6530     left = tmp;
6531   }
6532
6533   /* if right is bit then exchange them */
6534   if (AOP_TYPE(right) == AOP_CRY &&
6535       AOP_TYPE(left) != AOP_CRY){
6536     operand *tmp = right ;
6537     right = left;
6538     left = tmp;
6539   }
6540   if(AOP_TYPE(right) == AOP_LIT)
6541     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6542
6543   size = AOP_SIZE(result);
6544
6545   // if(bit ^ yy)
6546   // xx = bit ^ yy;
6547   if (AOP_TYPE(left) == AOP_CRY){
6548     if(AOP_TYPE(right) == AOP_LIT){
6549       // c = bit & literal;
6550       if(lit>>1){
6551         // lit>>1  != 0 => result = 1
6552         if(AOP_TYPE(result) == AOP_CRY){
6553           if(size)
6554             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6555             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6556           else if(ifx)
6557             continueIfTrue(ifx);
6558           goto release;
6559         }
6560         pic16_emitcode("setb","c");
6561       } else{
6562         // lit == (0 or 1)
6563         if(lit == 0){
6564           // lit == 0, result = left
6565           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6566             goto release;
6567           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6568         } else{
6569           // lit == 1, result = not(left)
6570           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6571             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6572             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6573             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6574             goto release;
6575           } else {
6576             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6577             pic16_emitcode("cpl","c");
6578           }
6579         }
6580       }
6581
6582     } else {
6583       // right != literal
6584       symbol *tlbl = newiTempLabel(NULL);
6585       if (AOP_TYPE(right) == AOP_CRY){
6586         // c = bit ^ bit;
6587         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6588       }
6589       else{
6590         int sizer = AOP_SIZE(right);
6591         // c = bit ^ val
6592         // if val>>1 != 0, result = 1
6593         pic16_emitcode("setb","c");
6594         while(sizer){
6595           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6596           if(sizer == 1)
6597             // test the msb of the lsb
6598             pic16_emitcode("anl","a,#0xfe");
6599           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6600           sizer--;
6601         }
6602         // val = (0,1)
6603         pic16_emitcode("rrc","a");
6604       }
6605       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6606       pic16_emitcode("cpl","c");
6607       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6608     }
6609     // bit = c
6610     // val = c
6611     if(size)
6612       pic16_outBitC(result);
6613     // if(bit | ...)
6614     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6615       genIfxJump(ifx, "c");           
6616     goto release ;
6617   }
6618
6619   if(pic16_sameRegs(AOP(result),AOP(left))){
6620     /* if left is same as result */
6621     for(;size--; offset++) {
6622       if(AOP_TYPE(right) == AOP_LIT){
6623         int t  = (lit >> (offset*8)) & 0x0FFL;
6624         if(t == 0x00L)
6625           continue;
6626         else
6627           if (IS_AOP_PREG(left)) {
6628             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6629             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6630             pic16_aopPut(AOP(result),"a",offset);
6631           } else {
6632             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6633             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6634             pic16_emitcode("xrl","%s,%s",
6635                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6636                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6637           }
6638       } else {
6639         if (AOP_TYPE(left) == AOP_ACC)
6640           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6641         else {
6642           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6643           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6644 /*
6645           if (IS_AOP_PREG(left)) {
6646             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6647             pic16_aopPut(AOP(result),"a",offset);
6648           } else
6649             pic16_emitcode("xrl","%s,a",
6650                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6651 */
6652         }
6653       }
6654     }
6655   } else {
6656     // left & result in different registers
6657     if(AOP_TYPE(result) == AOP_CRY){
6658       // result = bit
6659       // if(size), result in bit
6660       // if(!size && ifx), conditional oper: if(left ^ right)
6661       symbol *tlbl = newiTempLabel(NULL);
6662       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6663       if(size)
6664         pic16_emitcode("setb","c");
6665       while(sizer--){
6666         if((AOP_TYPE(right) == AOP_LIT) &&
6667            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6668           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6669         } else {
6670           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6671           pic16_emitcode("xrl","a,%s",
6672                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6673         }
6674         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6675         offset++;
6676       }
6677       if(size){
6678         CLRC;
6679         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6680         pic16_outBitC(result);
6681       } else if(ifx)
6682         jmpTrueOrFalse(ifx, tlbl);
6683     } else for(;(size--);offset++){
6684       // normal case
6685       // result = left & right
6686       if(AOP_TYPE(right) == AOP_LIT){
6687         int t = (lit >> (offset*8)) & 0x0FFL;
6688         switch(t) { 
6689         case 0x00:
6690           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6691           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6692           pic16_emitcode("movf","%s,w",
6693                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6694           pic16_emitcode("movwf","%s",
6695                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6696           break;
6697         case 0xff:
6698           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6699           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6700           pic16_emitcode("comf","%s,w",
6701                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6702           pic16_emitcode("movwf","%s",
6703                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6704           break;
6705         default:
6706           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6707           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6708           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6709           pic16_emitcode("movlw","0x%x",t);
6710           pic16_emitcode("xorwf","%s,w",
6711                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6712           pic16_emitcode("movwf","%s",
6713                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6714
6715         }
6716         continue;
6717       }
6718
6719       // faster than result <- left, anl result,right
6720       // and better if result is SFR
6721       if (AOP_TYPE(left) == AOP_ACC) {
6722         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6723         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6724       } else {
6725         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6726         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6727         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6728         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6729       }
6730       if ( AOP_TYPE(result) != AOP_ACC){
6731         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6732         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6733       }
6734     }
6735   }
6736
6737   release :
6738     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6739   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6740   pic16_freeAsmop(result,NULL,ic,TRUE);     
6741 }
6742
6743 /*-----------------------------------------------------------------*/
6744 /* genInline - write the inline code out                           */
6745 /*-----------------------------------------------------------------*/
6746 static void genInline (iCode *ic)
6747 {
6748   char *buffer, *bp, *bp1;
6749     
6750         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6751
6752         _G.inLine += (!options.asmpeep);
6753
6754         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6755         strcpy(buffer,IC_INLINE(ic));
6756
6757 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6758
6759         /* emit each line as a code */
6760         while (*bp) {
6761                 if (*bp == '\n') {
6762                         *bp++ = '\0';
6763
6764                         if(*bp1)
6765                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6766                         bp1 = bp;
6767                 } else {
6768                         if (*bp == ':') {
6769                                 bp++;
6770                                 *bp = '\0';
6771                                 bp++;
6772
6773                                 /* print label, use this special format with NULL directive
6774                                  * to denote that the argument should not be indented with tab */
6775                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6776                                 bp1 = bp;
6777                         } else
6778                                 bp++;
6779                 }
6780         }
6781
6782         if ((bp1 != bp) && *bp1)
6783                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6784
6785
6786     Safe_free(buffer);
6787
6788     _G.inLine -= (!options.asmpeep);
6789 }
6790
6791 /*-----------------------------------------------------------------*/
6792 /* genRRC - rotate right with carry                                */
6793 /*-----------------------------------------------------------------*/
6794 static void genRRC (iCode *ic)
6795 {
6796   operand *left , *result ;
6797   int size, offset = 0, same;
6798
6799   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6800
6801   /* rotate right with carry */
6802   left = IC_LEFT(ic);
6803   result=IC_RESULT(ic);
6804   pic16_aopOp (left,ic,FALSE);
6805   pic16_aopOp (result,ic,FALSE);
6806
6807   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6808
6809   same = pic16_sameRegs(AOP(result),AOP(left));
6810
6811   size = AOP_SIZE(result);    
6812
6813   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6814
6815   /* get the lsb and put it into the carry */
6816   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6817
6818   offset = 0 ;
6819
6820   while(size--) {
6821
6822     if(same) {
6823       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6824     } else {
6825       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6826       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6827     }
6828
6829     offset++;
6830   }
6831
6832   pic16_freeAsmop(left,NULL,ic,TRUE);
6833   pic16_freeAsmop(result,NULL,ic,TRUE);
6834 }
6835
6836 /*-----------------------------------------------------------------*/
6837 /* genRLC - generate code for rotate left with carry               */
6838 /*-----------------------------------------------------------------*/
6839 static void genRLC (iCode *ic)
6840 {    
6841   operand *left , *result ;
6842   int size, offset = 0;
6843   int same;
6844
6845   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6846   /* rotate right with carry */
6847   left = IC_LEFT(ic);
6848   result=IC_RESULT(ic);
6849   pic16_aopOp (left,ic,FALSE);
6850   pic16_aopOp (result,ic,FALSE);
6851
6852   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6853
6854   same = pic16_sameRegs(AOP(result),AOP(left));
6855
6856   /* move it to the result */
6857   size = AOP_SIZE(result);    
6858
6859   /* get the msb and put it into the carry */
6860   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6861
6862   offset = 0 ;
6863
6864   while(size--) {
6865
6866     if(same) {
6867       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6868     } else {
6869       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6870       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6871     }
6872
6873     offset++;
6874   }
6875
6876
6877   pic16_freeAsmop(left,NULL,ic,TRUE);
6878   pic16_freeAsmop(result,NULL,ic,TRUE);
6879 }
6880
6881
6882 /* gpasm can get the highest order bit with HIGH/UPPER
6883  * so the following probably is not needed -- VR */
6884  
6885 /*-----------------------------------------------------------------*/
6886 /* genGetHbit - generates code get highest order bit               */
6887 /*-----------------------------------------------------------------*/
6888 static void genGetHbit (iCode *ic)
6889 {
6890     operand *left, *result;
6891     left = IC_LEFT(ic);
6892     result=IC_RESULT(ic);
6893     pic16_aopOp (left,ic,FALSE);
6894     pic16_aopOp (result,ic,FALSE);
6895
6896     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6897     /* get the highest order byte into a */
6898     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6899     if(AOP_TYPE(result) == AOP_CRY){
6900         pic16_emitcode("rlc","a");
6901         pic16_outBitC(result);
6902     }
6903     else{
6904         pic16_emitcode("rl","a");
6905         pic16_emitcode("anl","a,#0x01");
6906         pic16_outAcc(result);
6907     }
6908
6909
6910     pic16_freeAsmop(left,NULL,ic,TRUE);
6911     pic16_freeAsmop(result,NULL,ic,TRUE);
6912 }
6913
6914 #if 0
6915 /*-----------------------------------------------------------------*/
6916 /* AccRol - rotate left accumulator by known count                 */
6917 /*-----------------------------------------------------------------*/
6918 static void AccRol (int shCount)
6919 {
6920     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6921     shCount &= 0x0007;              // shCount : 0..7
6922     switch(shCount){
6923         case 0 :
6924             break;
6925         case 1 :
6926             pic16_emitcode("rl","a");
6927             break;
6928         case 2 :
6929             pic16_emitcode("rl","a");
6930             pic16_emitcode("rl","a");
6931             break;
6932         case 3 :
6933             pic16_emitcode("swap","a");
6934             pic16_emitcode("rr","a");
6935             break;
6936         case 4 :
6937             pic16_emitcode("swap","a");
6938             break;
6939         case 5 :
6940             pic16_emitcode("swap","a");
6941             pic16_emitcode("rl","a");
6942             break;
6943         case 6 :
6944             pic16_emitcode("rr","a");
6945             pic16_emitcode("rr","a");
6946             break;
6947         case 7 :
6948             pic16_emitcode("rr","a");
6949             break;
6950     }
6951 }
6952 #endif
6953
6954 /*-----------------------------------------------------------------*/
6955 /* AccLsh - left shift accumulator by known count                  */
6956 /*-----------------------------------------------------------------*/
6957 static void AccLsh (int shCount)
6958 {
6959         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6960         switch(shCount){
6961                 case 0 :
6962                         return;
6963                         break;
6964                 case 1 :
6965                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6966                         break;
6967                 case 2 :
6968                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6969                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6970                         break;
6971                 case 3 :
6972                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6973                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6974                         break;
6975                 case 4 :
6976                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6977                         break;
6978                 case 5 :
6979                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6980                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6981                         break;
6982                 case 6 :
6983                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6984                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6985                         break;
6986                 case 7 :
6987                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6988                         break;
6989         }
6990
6991         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6992 }
6993
6994 /*-----------------------------------------------------------------*/
6995 /* AccRsh - right shift accumulator by known count                 */
6996 /*-----------------------------------------------------------------*/
6997 static void AccRsh (int shCount, int andmask)
6998 {
6999         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7000         switch(shCount){
7001                 case 0 :
7002                         return; break;
7003                 case 1 :
7004                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7005 //                      andmask = 0;    /* no need */
7006                         break;
7007                 case 2 :
7008                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7009                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7010 //                      andmask = 0;    /* no need */
7011                         break;
7012                 case 3 :
7013                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7014                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7015                         break;
7016                 case 4 :
7017                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7018                         break;
7019                 case 5 :
7020                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7021                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7022                         break;
7023                 case 6 :
7024                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7025                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7026                         break;
7027                 case 7 :
7028                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7029                         break;
7030         }
7031         
7032         if(andmask)
7033                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7034         else
7035                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7036 }
7037
7038 #if 0
7039 /*-----------------------------------------------------------------*/
7040 /* AccSRsh - signed right shift accumulator by known count                 */
7041 /*-----------------------------------------------------------------*/
7042 static void AccSRsh (int shCount)
7043 {
7044     symbol *tlbl ;
7045     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7046     if(shCount != 0){
7047         if(shCount == 1){
7048             pic16_emitcode("mov","c,acc.7");
7049             pic16_emitcode("rrc","a");
7050         } else if(shCount == 2){
7051             pic16_emitcode("mov","c,acc.7");
7052             pic16_emitcode("rrc","a");
7053             pic16_emitcode("mov","c,acc.7");
7054             pic16_emitcode("rrc","a");
7055         } else {
7056             tlbl = newiTempLabel(NULL);
7057             /* rotate right accumulator */
7058             AccRol(8 - shCount);
7059             /* and kill the higher order bits */
7060             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7061             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7062             pic16_emitcode("orl","a,#0x%02x",
7063                      (unsigned char)~SRMask[shCount]);
7064             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7065         }
7066     }
7067 }
7068 #endif
7069 /*-----------------------------------------------------------------*/
7070 /* shiftR1Left2Result - shift right one byte from left to result   */
7071 /*-----------------------------------------------------------------*/
7072 static void shiftR1Left2ResultSigned (operand *left, int offl,
7073                                 operand *result, int offr,
7074                                 int shCount)
7075 {
7076   int same;
7077
7078   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7079
7080   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7081
7082   switch(shCount) {
7083   case 1:
7084     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7085     if(same) 
7086       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7087     else {
7088       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7089       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7090     }
7091
7092     break;
7093   case 2:
7094
7095     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7096     if(same) 
7097       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7098     else {
7099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7100       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7101     }
7102     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7103     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7104
7105     break;
7106
7107   case 3:
7108     if(same)
7109       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7110     else {
7111       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7112       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7113     }
7114
7115     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7116     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7117     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7118
7119     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7120     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7121
7122     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7123     break;
7124
7125   case 4:
7126     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7127     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7128     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7129     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7130     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7131     break;
7132   case 5:
7133     if(same) {
7134       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7135     } else {
7136       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7137       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7138     }
7139     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7140     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7141     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7142     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7143     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7144     break;
7145
7146   case 6:
7147     if(same) {
7148       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7149       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7150       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7151       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7152       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7153       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7154     } else {
7155       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7156       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7157       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7158       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7159       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7160     }
7161     break;
7162
7163   case 7:
7164     if(same) {
7165       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7166       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7167       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7168       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7169     } else {
7170       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7171       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7172       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7173     }
7174
7175   default:
7176     break;
7177   }
7178 }
7179
7180 /*-----------------------------------------------------------------*/
7181 /* shiftR1Left2Result - shift right one byte from left to result   */
7182 /*-----------------------------------------------------------------*/
7183 static void shiftR1Left2Result (operand *left, int offl,
7184                                 operand *result, int offr,
7185                                 int shCount, int sign)
7186 {
7187   int same;
7188
7189   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7190
7191   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7192
7193   /* Copy the msb into the carry if signed. */
7194   if(sign) {
7195     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7196     return;
7197   }
7198
7199
7200
7201   switch(shCount) {
7202   case 1:
7203     emitCLRC;
7204     if(same) 
7205       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7206     else {
7207       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7208       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7209     }
7210     break;
7211   case 2:
7212     emitCLRC;
7213     if(same) {
7214       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7215     } else {
7216       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7217       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7218     }
7219     emitCLRC;
7220     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7221
7222     break;
7223   case 3:
7224     if(same)
7225       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7226     else {
7227       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7228       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7229     }
7230
7231     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7232     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7233     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7234     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7235     break;
7236       
7237   case 4:
7238     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7239     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7240     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7241     break;
7242
7243   case 5:
7244     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7245     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7246     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7247     emitCLRC;
7248     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7249
7250     break;
7251   case 6:
7252
7253     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7254     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7255     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7256     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7257     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7258     break;
7259
7260   case 7:
7261
7262     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7263     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7264     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7265
7266     break;
7267
7268   default:
7269     break;
7270   }
7271 }
7272
7273 /*-----------------------------------------------------------------*/
7274 /* shiftL1Left2Result - shift left one byte from left to result    */
7275 /*-----------------------------------------------------------------*/
7276 static void shiftL1Left2Result (operand *left, int offl,
7277                                 operand *result, int offr, int shCount)
7278 {
7279   int same;
7280
7281   //    char *l;
7282   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7283
7284   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7285   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7286     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7287     //    MOVA(l);
7288     /* shift left accumulator */
7289     //AccLsh(shCount); // don't comment out just yet...
7290   //    pic16_aopPut(AOP(result),"a",offr);
7291
7292   switch(shCount) {
7293   case 1:
7294     /* Shift left 1 bit position */
7295     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7296     if(same) {
7297       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7298     } else {
7299       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7300       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7301     }
7302     break;
7303   case 2:
7304     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7305     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7306     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7307     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7308     break;
7309   case 3:
7310     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7311     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7312     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7313     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7314     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7315     break;
7316   case 4:
7317     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7318     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7319     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7320     break;
7321   case 5:
7322     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7323     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7324     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7325     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7326     break;
7327   case 6:
7328     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7329     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7330     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7331     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7332     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7333     break;
7334   case 7:
7335     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7336     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7337     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7338     break;
7339
7340   default:
7341     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7342   }
7343
7344 }
7345
7346 /*-----------------------------------------------------------------*/
7347 /* movLeft2Result - move byte from left to result                  */
7348 /*-----------------------------------------------------------------*/
7349 static void movLeft2Result (operand *left, int offl,
7350                             operand *result, int offr)
7351 {
7352   char *l;
7353   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7354   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7355     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7356
7357     if (*l == '@' && (IS_AOP_PREG(result))) {
7358       pic16_emitcode("mov","a,%s",l);
7359       pic16_aopPut(AOP(result),"a",offr);
7360     } else {
7361       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7362       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7363     }
7364   }
7365 }
7366
7367 /*-----------------------------------------------------------------*/
7368 /* shiftL2Left2Result - shift left two bytes from left to result   */
7369 /*-----------------------------------------------------------------*/
7370 static void shiftL2Left2Result (operand *left, int offl,
7371                                 operand *result, int offr, int shCount)
7372 {
7373   int same = pic16_sameRegs(AOP(result), AOP(left));
7374   int i;
7375
7376   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7377
7378   if (same && (offl != offr)) { // shift bytes
7379     if (offr > offl) {
7380        for(i=1;i>-1;i--) {
7381          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7382          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7383        }
7384     } else { // just treat as different later on
7385                 same = 0;
7386     }
7387   }
7388
7389   if(same) {
7390     switch(shCount) {
7391     case 0:
7392       break;
7393     case 1:
7394     case 2:
7395     case 3:
7396
7397       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7398       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7399       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7400
7401       while(--shCount) {
7402                 emitCLRC;
7403                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7404                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7405       }
7406
7407       break;
7408     case 4:
7409     case 5:
7410       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7411       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7412       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7413       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7414       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7415       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7416       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7417       if(shCount >=5) {
7418                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7419                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7420       }
7421       break;
7422     case 6:
7423       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7424       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7425       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7426       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7427       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7428       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7429       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7430       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7431       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7432       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7433       break;
7434     case 7:
7435       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7436       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7437       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7438       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7439       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7440     }
7441
7442   } else {
7443     switch(shCount) {
7444     case 0:
7445       break;
7446     case 1:
7447     case 2:
7448     case 3:
7449       /* note, use a mov/add for the shift since the mov has a
7450          chance of getting optimized out */
7451       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7452       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7453       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7454       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7455       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7456
7457       while(--shCount) {
7458                 emitCLRC;
7459                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7460                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7461       }
7462       break;
7463
7464     case 4:
7465     case 5:
7466       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7467       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7468       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7469       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7470       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7471       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7472       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7473       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7474
7475
7476       if(shCount == 5) {
7477                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7478                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7479       }
7480       break;
7481     case 6:
7482       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7483       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7484       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7485       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7486
7487       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7488       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7489       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7490       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7491       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7492       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7493       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7494       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7495       break;
7496     case 7:
7497       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7498       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7499       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7500       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7501       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7502     }
7503   }
7504
7505 }
7506 /*-----------------------------------------------------------------*/
7507 /* shiftR2Left2Result - shift right two bytes from left to result  */
7508 /*-----------------------------------------------------------------*/
7509 static void shiftR2Left2Result (operand *left, int offl,
7510                                 operand *result, int offr,
7511                                 int shCount, int sign)
7512 {
7513   int same = pic16_sameRegs(AOP(result), AOP(left));
7514   int i;
7515   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7516
7517   if (same && (offl != offr)) { // shift right bytes
7518     if (offr < offl) {
7519        for(i=0;i<2;i++) {
7520          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7521          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7522        }
7523     } else { // just treat as different later on
7524                 same = 0;
7525     }
7526   }
7527
7528   switch(shCount) {
7529   case 0:
7530     break;
7531   case 1:
7532   case 2:
7533   case 3:
7534     if(sign)
7535       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7536     else
7537       emitCLRC;
7538
7539     if(same) {
7540       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7541       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7542     } else {
7543       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7544       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7545       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7546       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7547     }
7548
7549     while(--shCount) {
7550       if(sign)
7551                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7552       else
7553                 emitCLRC;
7554       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7555       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7556     }
7557     break;
7558   case 4:
7559   case 5:
7560     if(same) {
7561
7562       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7563       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7564       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7565
7566       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7567       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7568       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7569       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7570     } else {
7571       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7572       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7573       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7574
7575       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7576       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7577       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7578       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7579       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7580     }
7581
7582     if(shCount >=5) {
7583       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7584       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7585     }
7586
7587     if(sign) {
7588       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7589       pic16_emitpcode(POC_BTFSC, 
7590                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7591       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7592     }
7593
7594     break;
7595
7596   case 6:
7597     if(same) {
7598
7599       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7600       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7601
7602       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7603       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7604       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7605       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7606       if(sign) {
7607         pic16_emitpcode(POC_BTFSC, 
7608                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7609         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7610       }
7611       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7612       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7613       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7614       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7615     } else {
7616       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7617       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7618       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7619       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7620       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7621       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7622       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7623       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7624       if(sign) {
7625         pic16_emitpcode(POC_BTFSC, 
7626                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7627         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7628       }
7629       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7630       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7631
7632         
7633     }
7634
7635     break;
7636   case 7:
7637     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7638     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7639     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7640     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7641     if(sign) {
7642       emitSKPNC;
7643       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7644     } else 
7645       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7646   }
7647 }
7648
7649
7650 /*-----------------------------------------------------------------*/
7651 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7652 /*-----------------------------------------------------------------*/
7653 static void shiftLLeftOrResult (operand *left, int offl,
7654                                 operand *result, int offr, int shCount)
7655 {
7656     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7657
7658     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7659     /* shift left accumulator */
7660     AccLsh(shCount);
7661     /* or with result */
7662     /* back to result */
7663     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7664 }
7665
7666 /*-----------------------------------------------------------------*/
7667 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7668 /*-----------------------------------------------------------------*/
7669 static void shiftRLeftOrResult (operand *left, int offl,
7670                                 operand *result, int offr, int shCount)
7671 {
7672     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7673     
7674     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7675     /* shift right accumulator */
7676     AccRsh(shCount, 1);
7677     /* or with result */
7678     /* back to result */
7679     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7680 }
7681
7682 /*-----------------------------------------------------------------*/
7683 /* genlshOne - left shift a one byte quantity by known count       */
7684 /*-----------------------------------------------------------------*/
7685 static void genlshOne (operand *result, operand *left, int shCount)
7686 {       
7687     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7688     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7689 }
7690
7691 /*-----------------------------------------------------------------*/
7692 /* genlshTwo - left shift two bytes by known amount != 0           */
7693 /*-----------------------------------------------------------------*/
7694 static void genlshTwo (operand *result,operand *left, int shCount)
7695 {
7696     int size;
7697     
7698     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7699     size = pic16_getDataSize(result);
7700
7701     /* if shCount >= 8 */
7702     if (shCount >= 8) {
7703         shCount -= 8 ;
7704
7705         if (size > 1){
7706             if (shCount)
7707                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7708             else 
7709                 movLeft2Result(left, LSB, result, MSB16);
7710         }
7711         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7712     }
7713
7714     /*  1 <= shCount <= 7 */
7715     else {  
7716         if(size == 1)
7717             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7718         else 
7719             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7720     }
7721 }
7722
7723 /*-----------------------------------------------------------------*/
7724 /* shiftLLong - shift left one long from left to result            */
7725 /* offr = LSB or MSB16                                             */
7726 /*-----------------------------------------------------------------*/
7727 static void shiftLLong (operand *left, operand *result, int offr )
7728 {
7729     int size = AOP_SIZE(result);
7730     int same = pic16_sameRegs(AOP(left),AOP(result));
7731         int i;
7732
7733     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7734
7735         if (same && (offr == MSB16)) { //shift one byte
7736                 for(i=size-1;i>=MSB16;i--) {
7737                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7738                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7739                 }
7740         } else {
7741                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7742         }
7743         
7744     if (size >= LSB+offr ){
7745                 if (same) {
7746                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7747                 } else {
7748                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7749                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7750                 }
7751          }
7752
7753     if(size >= MSB16+offr){
7754                 if (same) {
7755                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7756                 } else {
7757                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7758                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7759                 }
7760     }
7761
7762     if(size >= MSB24+offr){
7763                 if (same) {
7764                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7765                 } else {
7766                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7767                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7768                 }
7769     }
7770
7771     if(size > MSB32+offr){
7772                 if (same) {
7773                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7774                 } else {
7775                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7776                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7777                 }
7778     }
7779     if(offr != LSB)
7780                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7781
7782 }
7783
7784 /*-----------------------------------------------------------------*/
7785 /* genlshFour - shift four byte by a known amount != 0             */
7786 /*-----------------------------------------------------------------*/
7787 static void genlshFour (operand *result, operand *left, int shCount)
7788 {
7789     int size;
7790
7791     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7792     size = AOP_SIZE(result);
7793
7794     /* if shifting more that 3 bytes */
7795     if (shCount >= 24 ) {
7796         shCount -= 24;
7797         if (shCount)
7798             /* lowest order of left goes to the highest
7799             order of the destination */
7800             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7801         else
7802             movLeft2Result(left, LSB, result, MSB32);
7803
7804                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7805                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7806                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7807
7808         return;
7809     }
7810
7811     /* more than two bytes */
7812     else if ( shCount >= 16 ) {
7813         /* lower order two bytes goes to higher order two bytes */
7814         shCount -= 16;
7815         /* if some more remaining */
7816         if (shCount)
7817             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7818         else {
7819             movLeft2Result(left, MSB16, result, MSB32);
7820             movLeft2Result(left, LSB, result, MSB24);
7821         }
7822                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7823                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7824         return;
7825     }    
7826
7827     /* if more than 1 byte */
7828     else if ( shCount >= 8 ) {
7829         /* lower order three bytes goes to higher order  three bytes */
7830         shCount -= 8;
7831         if(size == 2){
7832             if(shCount)
7833                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7834             else
7835                 movLeft2Result(left, LSB, result, MSB16);
7836         }
7837         else{   /* size = 4 */
7838             if(shCount == 0){
7839                 movLeft2Result(left, MSB24, result, MSB32);
7840                 movLeft2Result(left, MSB16, result, MSB24);
7841                 movLeft2Result(left, LSB, result, MSB16);
7842                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7843             }
7844             else if(shCount == 1)
7845                 shiftLLong(left, result, MSB16);
7846             else{
7847                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7848                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7849                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7850                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7851             }
7852         }
7853     }
7854
7855     /* 1 <= shCount <= 7 */
7856     else if(shCount <= 3)
7857     { 
7858         shiftLLong(left, result, LSB);
7859         while(--shCount >= 1)
7860             shiftLLong(result, result, LSB);
7861     }
7862     /* 3 <= shCount <= 7, optimize */
7863     else{
7864         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7865         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7866         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7867     }
7868 }
7869
7870 /*-----------------------------------------------------------------*/
7871 /* genLeftShiftLiteral - left shifting by known count              */
7872 /*-----------------------------------------------------------------*/
7873 static void genLeftShiftLiteral (operand *left,
7874                                  operand *right,
7875                                  operand *result,
7876                                  iCode *ic)
7877 {    
7878     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7879     int size;
7880
7881     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7882     pic16_freeAsmop(right,NULL,ic,TRUE);
7883
7884     pic16_aopOp(left,ic,FALSE);
7885     pic16_aopOp(result,ic,FALSE);
7886
7887     size = getSize(operandType(result));
7888
7889 #if VIEW_SIZE
7890     pic16_emitcode("; shift left ","result %d, left %d",size,
7891              AOP_SIZE(left));
7892 #endif
7893
7894     /* I suppose that the left size >= result size */
7895     if(shCount == 0){
7896         while(size--){
7897             movLeft2Result(left, size, result, size);
7898         }
7899     }
7900
7901     else if(shCount >= (size * 8))
7902         while(size--)
7903             pic16_aopPut(AOP(result),zero,size);
7904     else{
7905         switch (size) {
7906             case 1:
7907                 genlshOne (result,left,shCount);
7908                 break;
7909
7910             case 2:
7911             case 3:
7912                 genlshTwo (result,left,shCount);
7913                 break;
7914
7915             case 4:
7916                 genlshFour (result,left,shCount);
7917                 break;
7918         }
7919     }
7920     pic16_freeAsmop(left,NULL,ic,TRUE);
7921     pic16_freeAsmop(result,NULL,ic,TRUE);
7922 }
7923
7924 /*-----------------------------------------------------------------*
7925  * genMultiAsm - repeat assembly instruction for size of register.
7926  * if endian == 1, then the high byte (i.e base address + size of 
7927  * register) is used first else the low byte is used first;
7928  *-----------------------------------------------------------------*/
7929 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7930 {
7931
7932   int offset = 0;
7933
7934   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7935
7936   if(!reg)
7937     return;
7938
7939   if(!endian) {
7940     endian = 1;
7941   } else {
7942     endian = -1;
7943     offset = size-1;
7944   }
7945
7946   while(size--) {
7947     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7948     offset += endian;
7949   }
7950
7951 }
7952 /*-----------------------------------------------------------------*/
7953 /* genLeftShift - generates code for left shifting                 */
7954 /*-----------------------------------------------------------------*/
7955 static void genLeftShift (iCode *ic)
7956 {
7957   operand *left,*right, *result;
7958   int size, offset;
7959   char *l;
7960   symbol *tlbl , *tlbl1;
7961   pCodeOp *pctemp;
7962
7963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7964
7965   right = IC_RIGHT(ic);
7966   left  = IC_LEFT(ic);
7967   result = IC_RESULT(ic);
7968
7969   pic16_aopOp(right,ic,FALSE);
7970
7971   /* if the shift count is known then do it 
7972      as efficiently as possible */
7973   if (AOP_TYPE(right) == AOP_LIT) {
7974     genLeftShiftLiteral (left,right,result,ic);
7975     return ;
7976   }
7977
7978   /* shift count is unknown then we have to form 
7979      a loop get the loop count in B : Note: we take
7980      only the lower order byte since shifting
7981      more that 32 bits make no sense anyway, ( the
7982      largest size of an object can be only 32 bits ) */  
7983
7984     
7985   pic16_aopOp(left,ic,FALSE);
7986   pic16_aopOp(result,ic,FALSE);
7987
7988   /* now move the left to the result if they are not the
7989      same */
7990   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7991       AOP_SIZE(result) > 1) {
7992
7993     size = AOP_SIZE(result);
7994     offset=0;
7995     while (size--) {
7996       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7997       if (*l == '@' && (IS_AOP_PREG(result))) {
7998
7999         pic16_emitcode("mov","a,%s",l);
8000         pic16_aopPut(AOP(result),"a",offset);
8001       } else {
8002         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8003         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8004         //pic16_aopPut(AOP(result),l,offset);
8005       }
8006       offset++;
8007     }
8008   }
8009
8010   size = AOP_SIZE(result);
8011
8012   /* if it is only one byte then */
8013   if (size == 1) {
8014     if(optimized_for_speed) {
8015       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8016       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8017       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8018       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8019       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8020       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8021       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8022       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8023       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8024       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8025       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8026       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8027     } else {
8028
8029       tlbl = newiTempLabel(NULL);
8030       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8031                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8032                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8033       }
8034
8035       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8036       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8037       pic16_emitpLabel(tlbl->key);
8038       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8039       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8040       emitSKPC;
8041       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8042     }
8043     goto release ;
8044   }
8045     
8046   if (pic16_sameRegs(AOP(left),AOP(result))) {
8047
8048     tlbl = newiTempLabel(NULL);
8049     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8050     genMultiAsm(POC_RRCF, result, size,1);
8051     pic16_emitpLabel(tlbl->key);
8052     genMultiAsm(POC_RLCF, result, size,0);
8053     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8054     emitSKPC;
8055     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8056     goto release;
8057   }
8058
8059   //tlbl = newiTempLabel(NULL);
8060   //offset = 0 ;   
8061   //tlbl1 = newiTempLabel(NULL);
8062
8063   //reAdjustPreg(AOP(result));    
8064     
8065   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8066   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8067   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8068   //MOVA(l);
8069   //pic16_emitcode("add","a,acc");         
8070   //pic16_aopPut(AOP(result),"a",offset++);
8071   //while (--size) {
8072   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8073   //  MOVA(l);
8074   //  pic16_emitcode("rlc","a");         
8075   //  pic16_aopPut(AOP(result),"a",offset++);
8076   //}
8077   //reAdjustPreg(AOP(result));
8078
8079   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8080   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8081
8082
8083   tlbl = newiTempLabel(NULL);
8084   tlbl1= newiTempLabel(NULL);
8085
8086   size = AOP_SIZE(result);
8087   offset = 1;
8088
8089   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8090
8091   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8092
8093   /* offset should be 0, 1 or 3 */
8094   
8095   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8096   emitSKPNZ;
8097   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8098
8099   pic16_emitpcode(POC_MOVWF, pctemp);
8100
8101
8102   pic16_emitpLabel(tlbl->key);
8103
8104   emitCLRC;
8105   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8106   while(--size)
8107     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8108
8109   pic16_emitpcode(POC_DECFSZ,  pctemp);
8110   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8111   pic16_emitpLabel(tlbl1->key);
8112
8113   pic16_popReleaseTempReg(pctemp);
8114
8115
8116  release:
8117   pic16_freeAsmop (right,NULL,ic,TRUE);
8118   pic16_freeAsmop(left,NULL,ic,TRUE);
8119   pic16_freeAsmop(result,NULL,ic,TRUE);
8120 }
8121
8122 /*-----------------------------------------------------------------*/
8123 /* genrshOne - right shift a one byte quantity by known count      */
8124 /*-----------------------------------------------------------------*/
8125 static void genrshOne (operand *result, operand *left,
8126                        int shCount, int sign)
8127 {
8128     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8129     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8130 }
8131
8132 /*-----------------------------------------------------------------*/
8133 /* genrshTwo - right shift two bytes by known amount != 0          */
8134 /*-----------------------------------------------------------------*/
8135 static void genrshTwo (operand *result,operand *left,
8136                        int shCount, int sign)
8137 {
8138   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8139   /* if shCount >= 8 */
8140   if (shCount >= 8) {
8141     shCount -= 8 ;
8142     if (shCount)
8143       shiftR1Left2Result(left, MSB16, result, LSB,
8144                          shCount, sign);
8145     else
8146       movLeft2Result(left, MSB16, result, LSB);
8147
8148     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8149
8150     if(sign) {
8151       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8152       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8153     }
8154   }
8155
8156   /*  1 <= shCount <= 7 */
8157   else
8158     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8159 }
8160
8161 /*-----------------------------------------------------------------*/
8162 /* shiftRLong - shift right one long from left to result           */
8163 /* offl = LSB or MSB16                                             */
8164 /*-----------------------------------------------------------------*/
8165 static void shiftRLong (operand *left, int offl,
8166                         operand *result, int sign)
8167 {
8168     int size = AOP_SIZE(result);
8169     int same = pic16_sameRegs(AOP(left),AOP(result));
8170     int i;
8171     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8172
8173         if (same && (offl == MSB16)) { //shift one byte right
8174                 for(i=MSB16;i<size;i++) {
8175                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8176                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8177                 }
8178         }
8179
8180     if(sign)
8181                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8182         else
8183                 emitCLRC;
8184
8185         if (same) {
8186                 if (offl == LSB)
8187                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8188         } else {
8189         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8190         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8191         }
8192
8193     if(offl == MSB16) {
8194         /* add sign of "a" */
8195         pic16_addSign(result, MSB32, sign);
8196         }
8197
8198         if (same) {
8199         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8200         } else {
8201         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8202         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8203         }
8204         
8205         if (same) {
8206         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8207         } else {
8208         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8209         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8210         }
8211
8212         if (same) {
8213         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8214         } else {
8215         if(offl == LSB){
8216                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8217                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8218         }
8219         }
8220 }
8221
8222 /*-----------------------------------------------------------------*/
8223 /* genrshFour - shift four byte by a known amount != 0             */
8224 /*-----------------------------------------------------------------*/
8225 static void genrshFour (operand *result, operand *left,
8226                         int shCount, int sign)
8227 {
8228   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8229   /* if shifting more that 3 bytes */
8230   if(shCount >= 24 ) {
8231     shCount -= 24;
8232     if(shCount)
8233       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8234     else
8235       movLeft2Result(left, MSB32, result, LSB);
8236
8237     pic16_addSign(result, MSB16, sign);
8238   }
8239   else if(shCount >= 16){
8240     shCount -= 16;
8241     if(shCount)
8242       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8243     else{
8244       movLeft2Result(left, MSB24, result, LSB);
8245       movLeft2Result(left, MSB32, result, MSB16);
8246     }
8247     pic16_addSign(result, MSB24, sign);
8248   }
8249   else if(shCount >= 8){
8250     shCount -= 8;
8251     if(shCount == 1)
8252       shiftRLong(left, MSB16, result, sign);
8253     else if(shCount == 0){
8254       movLeft2Result(left, MSB16, result, LSB);
8255       movLeft2Result(left, MSB24, result, MSB16);
8256       movLeft2Result(left, MSB32, result, MSB24);
8257       pic16_addSign(result, MSB32, sign);
8258     }
8259     else{ //shcount >= 2
8260       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8261       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8262       /* the last shift is signed */
8263       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8264       pic16_addSign(result, MSB32, sign);
8265     }
8266   }
8267   else{   /* 1 <= shCount <= 7 */
8268     if(shCount <= 2){
8269       shiftRLong(left, LSB, result, sign);
8270       if(shCount == 2)
8271         shiftRLong(result, LSB, result, sign);
8272     }
8273     else{
8274       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8275       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8276       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8277     }
8278   }
8279 }
8280
8281 /*-----------------------------------------------------------------*/
8282 /* genRightShiftLiteral - right shifting by known count            */
8283 /*-----------------------------------------------------------------*/
8284 static void genRightShiftLiteral (operand *left,
8285                                   operand *right,
8286                                   operand *result,
8287                                   iCode *ic,
8288                                   int sign)
8289 {    
8290   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8291   int lsize,res_size;
8292
8293   pic16_freeAsmop(right,NULL,ic,TRUE);
8294
8295   pic16_aopOp(left,ic,FALSE);
8296   pic16_aopOp(result,ic,FALSE);
8297
8298   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8299
8300 #if VIEW_SIZE
8301   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8302                  AOP_SIZE(left));
8303 #endif
8304
8305   lsize = pic16_getDataSize(left);
8306   res_size = pic16_getDataSize(result);
8307   /* test the LEFT size !!! */
8308
8309   /* I suppose that the left size >= result size */
8310   if(shCount == 0){
8311     while(res_size--)
8312       movLeft2Result(left, lsize, result, res_size);
8313   }
8314
8315   else if(shCount >= (lsize * 8)){
8316
8317     if(res_size == 1) {
8318       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8319       if(sign) {
8320         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8321         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8322       }
8323     } else {
8324
8325       if(sign) {
8326         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8327         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8328         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8329         while(res_size--)
8330           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8331
8332       } else {
8333
8334         while(res_size--)
8335           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8336       }
8337     }
8338   } else {
8339
8340     switch (res_size) {
8341     case 1:
8342       genrshOne (result,left,shCount,sign);
8343       break;
8344
8345     case 2:
8346       genrshTwo (result,left,shCount,sign);
8347       break;
8348
8349     case 4:
8350       genrshFour (result,left,shCount,sign);
8351       break;
8352     default :
8353       break;
8354     }
8355
8356   }
8357
8358   pic16_freeAsmop(left,NULL,ic,TRUE);
8359   pic16_freeAsmop(result,NULL,ic,TRUE);
8360 }
8361
8362 /*-----------------------------------------------------------------*/
8363 /* genSignedRightShift - right shift of signed number              */
8364 /*-----------------------------------------------------------------*/
8365 static void genSignedRightShift (iCode *ic)
8366 {
8367   operand *right, *left, *result;
8368   int size, offset;
8369   //  char *l;
8370   symbol *tlbl, *tlbl1 ;
8371   pCodeOp *pctemp;
8372
8373   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8374
8375   /* we do it the hard way put the shift count in b
8376      and loop thru preserving the sign */
8377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8378
8379   right = IC_RIGHT(ic);
8380   left  = IC_LEFT(ic);
8381   result = IC_RESULT(ic);
8382
8383   pic16_aopOp(right,ic,FALSE);  
8384   pic16_aopOp(left,ic,FALSE);
8385   pic16_aopOp(result,ic,FALSE);
8386
8387
8388   if ( AOP_TYPE(right) == AOP_LIT) {
8389     genRightShiftLiteral (left,right,result,ic,1);
8390     return ;
8391   }
8392   /* shift count is unknown then we have to form 
8393      a loop get the loop count in B : Note: we take
8394      only the lower order byte since shifting
8395      more that 32 bits make no sense anyway, ( the
8396      largest size of an object can be only 32 bits ) */  
8397
8398   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8399   //pic16_emitcode("inc","b");
8400   //pic16_freeAsmop (right,NULL,ic,TRUE);
8401   //pic16_aopOp(left,ic,FALSE);
8402   //pic16_aopOp(result,ic,FALSE);
8403
8404   /* now move the left to the result if they are not the
8405      same */
8406   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8407       AOP_SIZE(result) > 1) {
8408
8409     size = AOP_SIZE(result);
8410     offset=0;
8411     while (size--) { 
8412       /*
8413         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8414         if (*l == '@' && IS_AOP_PREG(result)) {
8415
8416         pic16_emitcode("mov","a,%s",l);
8417         pic16_aopPut(AOP(result),"a",offset);
8418         } else
8419         pic16_aopPut(AOP(result),l,offset);
8420       */
8421       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8422       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8423
8424       offset++;
8425     }
8426   }
8427
8428   /* mov the highest order bit to OVR */    
8429   tlbl = newiTempLabel(NULL);
8430   tlbl1= newiTempLabel(NULL);
8431
8432   size = AOP_SIZE(result);
8433   offset = size - 1;
8434
8435   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8436
8437   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8438
8439   /* offset should be 0, 1 or 3 */
8440   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8441   emitSKPNZ;
8442   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8443
8444   pic16_emitpcode(POC_MOVWF, pctemp);
8445
8446
8447   pic16_emitpLabel(tlbl->key);
8448
8449   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8450   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8451
8452   while(--size) {
8453     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8454   }
8455
8456   pic16_emitpcode(POC_DECFSZ,  pctemp);
8457   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8458   pic16_emitpLabel(tlbl1->key);
8459
8460   pic16_popReleaseTempReg(pctemp);
8461 #if 0
8462   size = AOP_SIZE(result);
8463   offset = size - 1;
8464   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8465   pic16_emitcode("rlc","a");
8466   pic16_emitcode("mov","ov,c");
8467   /* if it is only one byte then */
8468   if (size == 1) {
8469     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8470     MOVA(l);
8471     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8472     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8473     pic16_emitcode("mov","c,ov");
8474     pic16_emitcode("rrc","a");
8475     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8476     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8477     pic16_aopPut(AOP(result),"a",0);
8478     goto release ;
8479   }
8480
8481   reAdjustPreg(AOP(result));
8482   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8483   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8484   pic16_emitcode("mov","c,ov");
8485   while (size--) {
8486     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8487     MOVA(l);
8488     pic16_emitcode("rrc","a");         
8489     pic16_aopPut(AOP(result),"a",offset--);
8490   }
8491   reAdjustPreg(AOP(result));
8492   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8493   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8494
8495  release:
8496 #endif
8497
8498   pic16_freeAsmop(left,NULL,ic,TRUE);
8499   pic16_freeAsmop(result,NULL,ic,TRUE);
8500   pic16_freeAsmop(right,NULL,ic,TRUE);
8501 }
8502
8503 /*-----------------------------------------------------------------*/
8504 /* genRightShift - generate code for right shifting                */
8505 /*-----------------------------------------------------------------*/
8506 static void genRightShift (iCode *ic)
8507 {
8508     operand *right, *left, *result;
8509     sym_link *letype ;
8510     int size, offset;
8511     char *l;
8512     symbol *tlbl, *tlbl1 ;
8513
8514     /* if signed then we do it the hard way preserve the
8515     sign bit moving it inwards */
8516     letype = getSpec(operandType(IC_LEFT(ic)));
8517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8518
8519     if (!SPEC_USIGN(letype)) {
8520         genSignedRightShift (ic);
8521         return ;
8522     }
8523
8524     /* signed & unsigned types are treated the same : i.e. the
8525     signed is NOT propagated inwards : quoting from the
8526     ANSI - standard : "for E1 >> E2, is equivalent to division
8527     by 2**E2 if unsigned or if it has a non-negative value,
8528     otherwise the result is implementation defined ", MY definition
8529     is that the sign does not get propagated */
8530
8531     right = IC_RIGHT(ic);
8532     left  = IC_LEFT(ic);
8533     result = IC_RESULT(ic);
8534
8535     pic16_aopOp(right,ic,FALSE);
8536
8537     /* if the shift count is known then do it 
8538     as efficiently as possible */
8539     if (AOP_TYPE(right) == AOP_LIT) {
8540         genRightShiftLiteral (left,right,result,ic, 0);
8541         return ;
8542     }
8543
8544     /* shift count is unknown then we have to form 
8545     a loop get the loop count in B : Note: we take
8546     only the lower order byte since shifting
8547     more that 32 bits make no sense anyway, ( the
8548     largest size of an object can be only 32 bits ) */  
8549
8550     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8551     pic16_emitcode("inc","b");
8552     pic16_aopOp(left,ic,FALSE);
8553     pic16_aopOp(result,ic,FALSE);
8554
8555     /* now move the left to the result if they are not the
8556     same */
8557     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8558         AOP_SIZE(result) > 1) {
8559
8560         size = AOP_SIZE(result);
8561         offset=0;
8562         while (size--) {
8563             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8564             if (*l == '@' && IS_AOP_PREG(result)) {
8565
8566                 pic16_emitcode("mov","a,%s",l);
8567                 pic16_aopPut(AOP(result),"a",offset);
8568             } else
8569                 pic16_aopPut(AOP(result),l,offset);
8570             offset++;
8571         }
8572     }
8573
8574     tlbl = newiTempLabel(NULL);
8575     tlbl1= newiTempLabel(NULL);
8576     size = AOP_SIZE(result);
8577     offset = size - 1;
8578
8579     /* if it is only one byte then */
8580     if (size == 1) {
8581
8582       tlbl = newiTempLabel(NULL);
8583       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8584         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8585         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8586       }
8587
8588       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8589       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8590       pic16_emitpLabel(tlbl->key);
8591       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8592       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8593       emitSKPC;
8594       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8595
8596       goto release ;
8597     }
8598
8599     reAdjustPreg(AOP(result));
8600     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8601     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8602     CLRC;
8603     while (size--) {
8604         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8605         MOVA(l);
8606         pic16_emitcode("rrc","a");         
8607         pic16_aopPut(AOP(result),"a",offset--);
8608     }
8609     reAdjustPreg(AOP(result));
8610
8611     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8612     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8613
8614 release:
8615     pic16_freeAsmop(left,NULL,ic,TRUE);
8616     pic16_freeAsmop (right,NULL,ic,TRUE);
8617     pic16_freeAsmop(result,NULL,ic,TRUE);
8618 }
8619
8620 /*-----------------------------------------------------------------*/
8621 /* genUnpackBits - generates code for unpacking bits               */
8622 /*-----------------------------------------------------------------*/
8623 static void genUnpackBits (operand *result, char *rname, int ptype)
8624 {    
8625     int shCnt ;
8626     int rlen = 0 ;
8627     sym_link *etype;
8628     int offset = 0 ;
8629
8630         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8631         etype = getSpec(operandType(result));
8632
8633         /* read the first byte  */
8634         switch (ptype) {
8635                 case POINTER:
8636                 case IPOINTER:
8637                 case PPOINTER:
8638                 case FPOINTER:
8639                 case GPOINTER:
8640                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8641                         break;
8642                 case CPOINTER:
8643                         pic16_emitcode("clr","a");
8644                         pic16_emitcode("movc","a","@a+dptr");
8645                         break;
8646         }
8647         
8648
8649         /* if we have bitdisplacement then it fits   */
8650         /* into this byte completely or if length is */
8651         /* less than a byte                          */
8652         if ((shCnt = SPEC_BSTR(etype)) || 
8653                 (SPEC_BLEN(etype) <= 8))  {
8654
8655                 /* shift right acc */
8656                 AccRsh(shCnt, 0);
8657
8658                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8659                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8660
8661 /* VR -- normally I would use the following, but since we use the hack,
8662  * to avoid the masking from AccRsh, why not mask it right now? */
8663
8664 /*
8665                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8666 */
8667
8668                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8669           return ;
8670         }
8671
8672
8673
8674         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8675         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8676         exit(-1);
8677
8678     /* bit field did not fit in a byte  */
8679     rlen = SPEC_BLEN(etype) - 8;
8680     pic16_aopPut(AOP(result),"a",offset++);
8681
8682     while (1)  {
8683
8684         switch (ptype) {
8685         case POINTER:
8686         case IPOINTER:
8687             pic16_emitcode("inc","%s",rname);
8688             pic16_emitcode("mov","a,@%s",rname);
8689             break;
8690             
8691         case PPOINTER:
8692             pic16_emitcode("inc","%s",rname);
8693             pic16_emitcode("movx","a,@%s",rname);
8694             break;
8695
8696         case FPOINTER:
8697             pic16_emitcode("inc","dptr");
8698             pic16_emitcode("movx","a,@dptr");
8699             break;
8700             
8701         case CPOINTER:
8702             pic16_emitcode("clr","a");
8703             pic16_emitcode("inc","dptr");
8704             pic16_emitcode("movc","a","@a+dptr");
8705             break;
8706             
8707         case GPOINTER:
8708             pic16_emitcode("inc","dptr");
8709             pic16_emitcode("lcall","__gptrget");
8710             break;
8711         }
8712
8713         rlen -= 8;            
8714         /* if we are done */
8715         if ( rlen <= 0 )
8716             break ;
8717         
8718         pic16_aopPut(AOP(result),"a",offset++);
8719                               
8720     }
8721     
8722     if (rlen) {
8723         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8724         pic16_aopPut(AOP(result),"a",offset);          
8725     }
8726     
8727     return ;
8728 }
8729
8730
8731 static void genDataPointerGet(operand *left,
8732                               operand *result,
8733                               iCode *ic)
8734 {
8735   int size, offset = 0, leoffset=0 ;
8736
8737         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8738         pic16_aopOp(result, ic, FALSE);
8739
8740         size = AOP_SIZE(result);
8741 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8742
8743
8744 #if 0
8745         /* The following tests may save a redudant movff instruction when
8746          * accessing unions */
8747          
8748         /* if they are the same */
8749         if (operandsEqu (left, result)) {
8750                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8751                 goto release;
8752         }
8753
8754         /* if they are the same registers */
8755         if (pic16_sameRegs(AOP(left),AOP(result))) {
8756                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8757                 goto release;
8758         }
8759 #endif
8760
8761 #if 0
8762         if ( AOP_TYPE(left) == AOP_PCODE) {
8763                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
8764                                 AOP(left)->aopu.pcop->name,
8765                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
8766                                 PCOR(AOP(left)->aopu.pcop)->instance:
8767                                 PCOI(AOP(left)->aopu.pcop)->offset);
8768         }
8769 #endif
8770
8771         if(AOP(left)->aopu.pcop->type == PO_DIR)
8772                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8773
8774         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8775
8776         while (size--) {
8777                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8778                 
8779                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8780                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8781                         mov2w(AOP(left), offset); // patch 8
8782                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8783                 } else {
8784                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8785                                 pic16_popGet(AOP(left), offset), //patch 8
8786                                 pic16_popGet(AOP(result), offset)));
8787                 }
8788
8789                 offset++;
8790                 leoffset++;
8791         }
8792
8793 //release:
8794     pic16_freeAsmop(result,NULL,ic,TRUE);
8795 }
8796
8797 void pic16_loadFSR0(operand *op)
8798 {
8799         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8800 }
8801
8802
8803 /*-----------------------------------------------------------------*/
8804 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8805 /*-----------------------------------------------------------------*/
8806 static void genNearPointerGet (operand *left, 
8807                                operand *result, 
8808                                iCode *ic)
8809 {
8810     asmop *aop = NULL;
8811     //regs *preg = NULL ;
8812     sym_link *rtype, *retype;
8813     sym_link *ltype = operandType(left);    
8814
8815         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8816         rtype = operandType(result);
8817         retype= getSpec(rtype);
8818     
8819         pic16_aopOp(left,ic,FALSE);
8820
8821         pic16_DumpOp("(left)",left);
8822         pic16_DumpOp("(result)",result);
8823
8824         /* if left is rematerialisable and
8825          * result is not bit variable type and
8826          * the left is pointer to data space i.e
8827          * lower 128 bytes of space */
8828         if (AOP_TYPE(left) == AOP_PCODE
8829                 && !IS_BITFIELD(retype)
8830                 && DCL_TYPE(ltype) == POINTER) {
8831
8832                 genDataPointerGet (left,result,ic);
8833                 pic16_freeAsmop(left, NULL, ic, TRUE);
8834           return ;
8835         }
8836     
8837         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838
8839         /* if the value is already in a pointer register
8840          * then don't need anything more */
8841         if (!AOP_INPREG(AOP(left))) {
8842                 /* otherwise get a free pointer register */
8843                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8844                 
8845                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8846                 if( (AOP_TYPE(left) == AOP_PCODE) 
8847                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8848                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
8849                 {
8850                         pic16_loadFSR0( left );  // patch 10
8851                 } else {
8852                         // set up FSR0 with address from left
8853                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
8854                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
8855                 }
8856         }
8857 //       else
8858 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8859     
8860         pic16_aopOp (result,ic,FALSE);
8861     
8862       /* if bitfield then unpack the bits */
8863     if (IS_BITFIELD(retype)) 
8864         genUnpackBits (result, NULL, POINTER);
8865     else {
8866         /* we have can just get the values */
8867       int size = AOP_SIZE(result);
8868       int offset = 0;   
8869         
8870       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8871
8872
8873         /* fsr0 is loaded already -- VR */
8874 //      pic16_loadFSR0( left );
8875
8876 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8877 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8878       while(size--) {
8879
8880         if(size) {
8881                 pic16_emitpcode(POC_MOVFF,
8882                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8883                                 pic16_popGet(AOP(result), offset++)));
8884         } else {
8885                 pic16_emitpcode(POC_MOVFF,
8886                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8887                                 pic16_popGet(AOP(result), offset++)));
8888         }
8889       }
8890 #if 0
8891 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8892 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8893         if(size)
8894           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8895 #endif
8896 /*
8897         while (size--) {
8898             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8899
8900                 pic16_emitcode("mov","a,@%s",rname);
8901                 pic16_aopPut(AOP(result),"a",offset);
8902             } else {
8903                 sprintf(buffer,"@%s",rname);
8904                 pic16_aopPut(AOP(result),buffer,offset);
8905             }
8906             offset++ ;
8907             if (size)
8908                 pic16_emitcode("inc","%s",rname);
8909         }
8910 */
8911     }
8912
8913     /* now some housekeeping stuff */
8914     if (aop) {
8915         /* we had to allocate for this iCode */
8916     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8917         pic16_freeAsmop(NULL,aop,ic,TRUE);
8918     } else { 
8919         /* we did not allocate which means left
8920            already in a pointer register, then
8921            if size > 0 && this could be used again
8922            we have to point it back to where it 
8923            belongs */
8924     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8925         if (AOP_SIZE(result) > 1 &&
8926             !OP_SYMBOL(left)->remat &&
8927             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8928               ic->depth )) {
8929 //          int size = AOP_SIZE(result) - 1;
8930 //          while (size--)
8931 //              pic16_emitcode("dec","%s",rname);
8932         }
8933     }
8934
8935     /* done */
8936     pic16_freeAsmop(left,NULL,ic,TRUE);
8937     pic16_freeAsmop(result,NULL,ic,TRUE);
8938      
8939 }
8940
8941 /*-----------------------------------------------------------------*/
8942 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8943 /*-----------------------------------------------------------------*/
8944 static void genPagedPointerGet (operand *left, 
8945                                operand *result, 
8946                                iCode *ic)
8947 {
8948     asmop *aop = NULL;
8949     regs *preg = NULL ;
8950     char *rname ;
8951     sym_link *rtype, *retype;    
8952
8953     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8954
8955     rtype = operandType(result);
8956     retype= getSpec(rtype);
8957     
8958     pic16_aopOp(left,ic,FALSE);
8959
8960   /* if the value is already in a pointer register
8961        then don't need anything more */
8962     if (!AOP_INPREG(AOP(left))) {
8963         /* otherwise get a free pointer register */
8964         aop = newAsmop(0);
8965         preg = getFreePtr(ic,&aop,FALSE);
8966         pic16_emitcode("mov","%s,%s",
8967                 preg->name,
8968                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8969         rname = preg->name ;
8970     } else
8971         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8972     
8973     pic16_freeAsmop(left,NULL,ic,TRUE);
8974     pic16_aopOp (result,ic,FALSE);
8975
8976     /* if bitfield then unpack the bits */
8977     if (IS_BITFIELD(retype)) 
8978         genUnpackBits (result,rname,PPOINTER);
8979     else {
8980         /* we have can just get the values */
8981         int size = AOP_SIZE(result);
8982         int offset = 0 ;        
8983         
8984         while (size--) {
8985             
8986             pic16_emitcode("movx","a,@%s",rname);
8987             pic16_aopPut(AOP(result),"a",offset);
8988             
8989             offset++ ;
8990             
8991             if (size)
8992                 pic16_emitcode("inc","%s",rname);
8993         }
8994     }
8995
8996     /* now some housekeeping stuff */
8997     if (aop) {
8998         /* we had to allocate for this iCode */
8999         pic16_freeAsmop(NULL,aop,ic,TRUE);
9000     } else { 
9001         /* we did not allocate which means left
9002            already in a pointer register, then
9003            if size > 0 && this could be used again
9004            we have to point it back to where it 
9005            belongs */
9006         if (AOP_SIZE(result) > 1 &&
9007             !OP_SYMBOL(left)->remat &&
9008             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9009               ic->depth )) {
9010             int size = AOP_SIZE(result) - 1;
9011             while (size--)
9012                 pic16_emitcode("dec","%s",rname);
9013         }
9014     }
9015
9016     /* done */
9017     pic16_freeAsmop(result,NULL,ic,TRUE);
9018     
9019         
9020 }
9021
9022 /*-----------------------------------------------------------------*/
9023 /* genFarPointerGet - gget value from far space                    */
9024 /*-----------------------------------------------------------------*/
9025 static void genFarPointerGet (operand *left,
9026                               operand *result, iCode *ic)
9027 {
9028     int size, offset ;
9029     sym_link *retype = getSpec(operandType(result));
9030
9031     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9032
9033     pic16_aopOp(left,ic,FALSE);
9034
9035     /* if the operand is already in dptr 
9036     then we do nothing else we move the value to dptr */
9037     if (AOP_TYPE(left) != AOP_STR) {
9038         /* if this is remateriazable */
9039         if (AOP_TYPE(left) == AOP_IMMD)
9040             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9041         else { /* we need to get it byte by byte */
9042             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9043             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9044             if (options.model == MODEL_FLAT24)
9045             {
9046                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9047             }
9048         }
9049     }
9050     /* so dptr know contains the address */
9051     pic16_freeAsmop(left,NULL,ic,TRUE);
9052     pic16_aopOp(result,ic,FALSE);
9053
9054     /* if bit then unpack */
9055     if (IS_BITFIELD(retype)) 
9056         genUnpackBits(result,"dptr",FPOINTER);
9057     else {
9058         size = AOP_SIZE(result);
9059         offset = 0 ;
9060
9061         while (size--) {
9062             pic16_emitcode("movx","a,@dptr");
9063             pic16_aopPut(AOP(result),"a",offset++);
9064             if (size)
9065                 pic16_emitcode("inc","dptr");
9066         }
9067     }
9068
9069     pic16_freeAsmop(result,NULL,ic,TRUE);
9070 }
9071 #if 0
9072 /*-----------------------------------------------------------------*/
9073 /* genCodePointerGet - get value from code space                  */
9074 /*-----------------------------------------------------------------*/
9075 static void genCodePointerGet (operand *left,
9076                                 operand *result, iCode *ic)
9077 {
9078     int size, offset ;
9079     sym_link *retype = getSpec(operandType(result));
9080
9081     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9082
9083     pic16_aopOp(left,ic,FALSE);
9084
9085     /* if the operand is already in dptr 
9086     then we do nothing else we move the value to dptr */
9087     if (AOP_TYPE(left) != AOP_STR) {
9088         /* if this is remateriazable */
9089         if (AOP_TYPE(left) == AOP_IMMD)
9090             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9091         else { /* we need to get it byte by byte */
9092             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9093             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9094             if (options.model == MODEL_FLAT24)
9095             {
9096                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9097             }
9098         }
9099     }
9100     /* so dptr know contains the address */
9101     pic16_freeAsmop(left,NULL,ic,TRUE);
9102     pic16_aopOp(result,ic,FALSE);
9103
9104     /* if bit then unpack */
9105     if (IS_BITFIELD(retype)) 
9106         genUnpackBits(result,"dptr",CPOINTER);
9107     else {
9108         size = AOP_SIZE(result);
9109         offset = 0 ;
9110
9111         while (size--) {
9112             pic16_emitcode("clr","a");
9113             pic16_emitcode("movc","a,@a+dptr");
9114             pic16_aopPut(AOP(result),"a",offset++);
9115             if (size)
9116                 pic16_emitcode("inc","dptr");
9117         }
9118     }
9119
9120     pic16_freeAsmop(result,NULL,ic,TRUE);
9121 }
9122 #endif
9123 /*-----------------------------------------------------------------*/
9124 /* genGenPointerGet - gget value from generic pointer space        */
9125 /*-----------------------------------------------------------------*/
9126 static void genGenPointerGet (operand *left,
9127                               operand *result, iCode *ic)
9128 {
9129   int size, offset, lit;
9130   sym_link *retype = getSpec(operandType(result));
9131
9132         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9133         pic16_aopOp(left,ic,FALSE);
9134         pic16_aopOp(result,ic,FALSE);
9135         size = AOP_SIZE(result);
9136
9137         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9138
9139         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9140
9141                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9142                 // load FSR0 from immediate
9143                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9144
9145 //              pic16_loadFSR0( left );
9146
9147                 offset = 0;
9148                 while(size--) {
9149                         if(size) {
9150                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9151                         } else {
9152                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9153                         }
9154                         offset++;
9155                 }
9156                 goto release;
9157
9158         }
9159         else { /* we need to get it byte by byte */
9160                 // set up FSR0 with address from left
9161                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9162                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9163
9164                 offset = 0 ;
9165
9166                 while(size--) {
9167                         if(size) {
9168                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9169                         } else {
9170                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9171                         }
9172                         offset++;
9173                 }
9174                 goto release;
9175         }
9176
9177   /* if bit then unpack */
9178         if (IS_BITFIELD(retype)) 
9179                 genUnpackBits(result,"BAD",GPOINTER);
9180
9181         release:
9182         pic16_freeAsmop(left,NULL,ic,TRUE);
9183         pic16_freeAsmop(result,NULL,ic,TRUE);
9184
9185 }
9186
9187 /*-----------------------------------------------------------------*/
9188 /* genConstPointerGet - get value from const generic pointer space */
9189 /*-----------------------------------------------------------------*/
9190 static void genConstPointerGet (operand *left,
9191                                 operand *result, iCode *ic)
9192 {
9193   //sym_link *retype = getSpec(operandType(result));
9194   // symbol *albl = newiTempLabel(NULL);        // patch 15
9195   // symbol *blbl = newiTempLabel(NULL);        //
9196   // PIC_OPCODE poc;                            // patch 15
9197   int size;
9198   int offset = 0;
9199
9200   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9201   pic16_aopOp(left,ic,FALSE);
9202   pic16_aopOp(result,ic,TRUE);
9203   size = AOP_SIZE(result);
9204
9205   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9206
9207   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9208 #if 0                                                                   // patch 15
9209   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9210   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9211   pic16_emitpLabel(albl->key);
9212
9213   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9214     
9215   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9216   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9217   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9218   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9219   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9220
9221   pic16_emitpLabel(blbl->key);
9222
9223   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9224 #endif                                                                  // patch 15
9225
9226
9227   // set up table pointer
9228   if( (AOP_TYPE(left) == AOP_PCODE) 
9229       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9230           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9231     {
9232       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9233       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9234       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9235       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9236       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9237       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9238     }
9239   else
9240     {
9241       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9242       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9243       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9244     }
9245
9246
9247   while(size--)
9248     {
9249       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9250       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9251       offset++;
9252     }
9253                                                                         // .... patch 15
9254   pic16_freeAsmop(left,NULL,ic,TRUE);
9255   pic16_freeAsmop(result,NULL,ic,TRUE);
9256
9257 }
9258 /*-----------------------------------------------------------------*/
9259 /* genPointerGet - generate code for pointer get                   */
9260 /*-----------------------------------------------------------------*/
9261 static void genPointerGet (iCode *ic)
9262 {
9263     operand *left, *result ;
9264     sym_link *type, *etype;
9265     int p_type;
9266
9267     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9268
9269     left = IC_LEFT(ic);
9270     result = IC_RESULT(ic) ;
9271
9272     /* depending on the type of pointer we need to
9273     move it to the correct pointer register */
9274     type = operandType(left);
9275     etype = getSpec(type);
9276
9277 #if 0
9278     if (IS_PTR_CONST(type))
9279 #else
9280     if (IS_CODEPTR(type))
9281 #endif
9282       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9283
9284     /* if left is of type of pointer then it is simple */
9285     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9286         p_type = DCL_TYPE(type);
9287     else {
9288         /* we have to go by the storage class */
9289         p_type = PTR_TYPE(SPEC_OCLS(etype));
9290
9291         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9292
9293         if (SPEC_OCLS(etype)->codesp ) {
9294           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9295           //p_type = CPOINTER ; 
9296         }
9297         else
9298             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9299               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9300                /*p_type = FPOINTER ;*/ 
9301             else
9302                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9303                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9304 /*                  p_type = PPOINTER; */
9305                 else
9306                     if (SPEC_OCLS(etype) == idata )
9307                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9308 /*                      p_type = IPOINTER; */
9309                     else
9310                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9311 /*                      p_type = POINTER ; */
9312     }
9313
9314     /* now that we have the pointer type we assign
9315     the pointer values */
9316     switch (p_type) {
9317
9318     case POINTER:       
9319     case IPOINTER:
9320         genNearPointerGet (left,result,ic);
9321         break;
9322
9323     case PPOINTER:
9324         genPagedPointerGet(left,result,ic);
9325         break;
9326
9327     case FPOINTER:
9328         genFarPointerGet (left,result,ic);
9329         break;
9330
9331     case CPOINTER:
9332         genConstPointerGet (left,result,ic);
9333         //pic16_emitcodePointerGet (left,result,ic);
9334         break;
9335
9336     case GPOINTER:
9337 #if 0
9338       if (IS_PTR_CONST(type))
9339         genConstPointerGet (left,result,ic);
9340       else
9341 #endif
9342         genGenPointerGet (left,result,ic);
9343       break;
9344     }
9345
9346 }
9347
9348 /*-----------------------------------------------------------------*/
9349 /* genPackBits - generates code for packed bit storage             */
9350 /*-----------------------------------------------------------------*/
9351 static void genPackBits (sym_link    *etype ,
9352                          operand *right ,
9353                          char *rname, int p_type)
9354 {
9355   int shCnt = 0 ;
9356   int offset = 0  ;
9357   int rLen = 0 ;
9358   int blen, bstr ;   
9359   char *l ;
9360
9361         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9362         blen = SPEC_BLEN(etype);
9363         bstr = SPEC_BSTR(etype);
9364
9365         if(AOP_TYPE(right) == AOP_LIT) {
9366                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9367                 offset++;
9368         } else
9369                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9370
9371 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9372         MOVA(l);   
9373 */
9374         /* if the bit lenth is less than or    */
9375         /* it exactly fits a byte then         */
9376         if((shCnt=SPEC_BSTR(etype))
9377                 || SPEC_BLEN(etype) <= 8 )  {
9378
9379                 /* shift left acc */
9380                 AccLsh(shCnt);
9381
9382                 /* using PRODL as a temporary register here */
9383                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9384
9385                 switch (p_type) {
9386                         case FPOINTER:
9387                         case POINTER:
9388                         case GPOINTER:
9389                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9390 //                              pic16_emitcode ("mov","b,a");
9391 //                              pic16_emitcode("mov","a,@%s",rname);
9392                                 break;
9393                 }
9394 #if 1
9395                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9396                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9397                                         (unsigned char)(0xff >> (8-bstr))) ));
9398                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9399                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9400 #endif
9401
9402 #if 0
9403                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9404                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9405                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9406                 pic16_emitcode ("orl","a,b");
9407                 if (p_type == GPOINTER)
9408                         pic16_emitcode("pop","b");
9409
9410                 
9411                 switch (p_type) {
9412                         case POINTER:
9413                                 pic16_emitcode("mov","@%s,a",rname);
9414                                 break;
9415                         case FPOINTER:
9416                                 pic16_emitcode("movx","@dptr,a");
9417                                 break;
9418                         case GPOINTER:
9419                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9420                                 break;
9421                 }
9422 #endif
9423
9424           return;
9425         }
9426
9427
9428         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9429         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9430         exit(-1);
9431
9432
9433     /* if we r done */
9434     if ( SPEC_BLEN(etype) <= 8 )
9435         return ;
9436
9437     pic16_emitcode("inc","%s",rname);
9438     rLen = SPEC_BLEN(etype) ;     
9439
9440
9441
9442     /* now generate for lengths greater than one byte */
9443     while (1) {
9444
9445         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9446
9447         rLen -= 8 ;
9448         if (rLen <= 0 )
9449             break ;
9450
9451         switch (p_type) {
9452             case POINTER:
9453                 if (*l == '@') {
9454                     MOVA(l);
9455                     pic16_emitcode("mov","@%s,a",rname);
9456                 } else
9457                     pic16_emitcode("mov","@%s,%s",rname,l);
9458                 break;
9459
9460             case FPOINTER:
9461                 MOVA(l);
9462                 pic16_emitcode("movx","@dptr,a");
9463                 break;
9464
9465             case GPOINTER:
9466                 MOVA(l);
9467                 DEBUGpic16_emitcode(";lcall","__gptrput");
9468                 break;  
9469         }   
9470         pic16_emitcode ("inc","%s",rname);
9471     }
9472
9473     MOVA(l);
9474
9475     /* last last was not complete */
9476     if (rLen)   {
9477         /* save the byte & read byte */
9478         switch (p_type) {
9479             case POINTER:
9480                 pic16_emitcode ("mov","b,a");
9481                 pic16_emitcode("mov","a,@%s",rname);
9482                 break;
9483
9484             case FPOINTER:
9485                 pic16_emitcode ("mov","b,a");
9486                 pic16_emitcode("movx","a,@dptr");
9487                 break;
9488
9489             case GPOINTER:
9490                 pic16_emitcode ("push","b");
9491                 pic16_emitcode ("push","acc");
9492                 pic16_emitcode ("lcall","__gptrget");
9493                 pic16_emitcode ("pop","b");
9494                 break;
9495         }
9496
9497         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9498         pic16_emitcode ("orl","a,b");
9499     }
9500
9501     if (p_type == GPOINTER)
9502         pic16_emitcode("pop","b");
9503
9504     switch (p_type) {
9505
9506     case POINTER:
9507         pic16_emitcode("mov","@%s,a",rname);
9508         break;
9509         
9510     case FPOINTER:
9511         pic16_emitcode("movx","@dptr,a");
9512         break;
9513         
9514     case GPOINTER:
9515         DEBUGpic16_emitcode(";lcall","__gptrput");
9516         break;                  
9517     }
9518 }
9519 /*-----------------------------------------------------------------*/
9520 /* genDataPointerSet - remat pointer to data space                 */
9521 /*-----------------------------------------------------------------*/
9522 static void genDataPointerSet(operand *right,
9523                               operand *result,
9524                               iCode *ic)
9525 {
9526     int size, offset = 0, resoffset=0 ;
9527
9528     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9529     pic16_aopOp(right,ic,FALSE);
9530
9531     size = AOP_SIZE(right);
9532
9533 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9534
9535 #if 0
9536     if ( AOP_TYPE(result) == AOP_PCODE) {
9537       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9538               AOP(result)->aopu.pcop->name,
9539                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9540               PCOR(AOP(result)->aopu.pcop)->instance:
9541               PCOI(AOP(result)->aopu.pcop)->offset);
9542     }
9543 #endif
9544
9545         if(AOP(result)->aopu.pcop->type == PO_DIR)
9546                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9547
9548         while (size--) {
9549                 if (AOP_TYPE(right) == AOP_LIT) {
9550                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9551
9552                         lit = lit >> (8*offset);
9553                         if(lit&0xff) {
9554                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9555                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9556                         } else {
9557                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9558                         }
9559                 } else {
9560                         mov2w(AOP(right), offset);
9561                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9562                 }
9563                 offset++;
9564                 resoffset++;
9565         }
9566
9567     pic16_freeAsmop(right,NULL,ic,TRUE);
9568 }
9569
9570
9571
9572 /*-----------------------------------------------------------------*/
9573 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9574 /*-----------------------------------------------------------------*/
9575 static void genNearPointerSet (operand *right,
9576                                operand *result, 
9577                                iCode *ic)
9578 {
9579   asmop *aop = NULL;
9580   char *l;
9581   sym_link *retype;
9582   sym_link *ptype = operandType(result);
9583   sym_link *resetype;
9584     
9585         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9586         retype= getSpec(operandType(right));
9587         resetype = getSpec(operandType(result));
9588   
9589         pic16_aopOp(result,ic,FALSE);
9590     
9591         /* if the result is rematerializable &
9592          * in data space & not a bit variable */
9593         
9594         /* and result is not a bit variable */
9595         if (AOP_TYPE(result) == AOP_PCODE
9596 //              && AOP_TYPE(result) == AOP_IMMD
9597                 && DCL_TYPE(ptype) == POINTER
9598                 && !IS_BITFIELD(retype)
9599                 && !IS_BITFIELD(resetype)) {
9600
9601                 genDataPointerSet (right,result,ic);
9602                 pic16_freeAsmop(result,NULL,ic,TRUE);
9603           return;
9604         }
9605
9606         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9607         pic16_aopOp(right,ic,FALSE);
9608         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9609
9610         /* if the value is already in a pointer register
9611          * then don't need anything more */
9612         if (!AOP_INPREG(AOP(result))) {
9613                 /* otherwise get a free pointer register */
9614                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9615
9616                 if( (AOP_TYPE(result) == AOP_PCODE) 
9617                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9618                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9619                 {
9620                         pic16_loadFSR0( result );  // patch 10
9621                 } else {
9622                         // set up FSR0 with address of result
9623                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9624                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9625                 }
9626
9627         }
9628 //      else
9629 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9630
9631         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9632
9633         /* if bitfield then unpack the bits */
9634         if (IS_BITFIELD(resetype)) {
9635                 genPackBits (resetype, right, NULL, POINTER);
9636         } else {
9637                 /* we have can just get the values */
9638           int size = AOP_SIZE(right);
9639           int offset = 0 ;    
9640
9641                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9642                 while (size--) {
9643                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9644                         if (*l == '@' ) {
9645                                 //MOVA(l);
9646                                 //pic16_emitcode("mov","@%s,a",rname);
9647                                 pic16_emitcode("movf","indf0,w ;1");
9648                         } else {
9649
9650                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9651                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9652                                         if (size) {                                                                     // 
9653                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9654                                         } else {                                                                        // 
9655                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9656                                         }                                                                               // 
9657                                 } else { // no literal                                                                  // 
9658                                         if(size) {                                                                      // 
9659                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9660                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9661                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9662                                         } else {                                                                        // 
9663                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9664                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9665                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9666                                         }                                                                               //
9667                                 }                                                                                       // patch 10
9668                         }
9669                         offset++;
9670                 }
9671         }
9672
9673         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9674         /* now some housekeeping stuff */
9675         if (aop) {
9676                 /* we had to allocate for this iCode */
9677                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9678         } else { 
9679                 /* we did not allocate which means left
9680                  * already in a pointer register, then
9681                  * if size > 0 && this could be used again
9682                  * we have to point it back to where it 
9683                  * belongs */
9684                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9685                 if (AOP_SIZE(right) > 1
9686                         && !OP_SYMBOL(result)->remat
9687                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9688                                 || ic->depth )) {
9689
9690                   int size = AOP_SIZE(right) - 1;
9691
9692                         while (size--)
9693                                 pic16_emitcode("decf","fsr0,f");
9694                         //pic16_emitcode("dec","%s",rname);
9695                 }
9696         }
9697
9698         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9699         /* done */
9700 //release:
9701         pic16_freeAsmop(right,NULL,ic,TRUE);
9702         pic16_freeAsmop(result,NULL,ic,TRUE);
9703 }
9704
9705 /*-----------------------------------------------------------------*/
9706 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9707 /*-----------------------------------------------------------------*/
9708 static void genPagedPointerSet (operand *right,
9709                                operand *result, 
9710                                iCode *ic)
9711 {
9712     asmop *aop = NULL;
9713     regs *preg = NULL ;
9714     char *rname , *l;
9715     sym_link *retype;
9716        
9717     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9718
9719     retype= getSpec(operandType(right));
9720     
9721     pic16_aopOp(result,ic,FALSE);
9722     
9723     /* if the value is already in a pointer register
9724        then don't need anything more */
9725     if (!AOP_INPREG(AOP(result))) {
9726         /* otherwise get a free pointer register */
9727         aop = newAsmop(0);
9728         preg = getFreePtr(ic,&aop,FALSE);
9729         pic16_emitcode("mov","%s,%s",
9730                 preg->name,
9731                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9732         rname = preg->name ;
9733     } else
9734         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9735     
9736     pic16_freeAsmop(result,NULL,ic,TRUE);
9737     pic16_aopOp (right,ic,FALSE);
9738
9739     /* if bitfield then unpack the bits */
9740     if (IS_BITFIELD(retype)) 
9741         genPackBits (retype,right,rname,PPOINTER);
9742     else {
9743         /* we have can just get the values */
9744         int size = AOP_SIZE(right);
9745         int offset = 0 ;        
9746         
9747         while (size--) {
9748             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9749             
9750             MOVA(l);
9751             pic16_emitcode("movx","@%s,a",rname);
9752
9753             if (size)
9754                 pic16_emitcode("inc","%s",rname);
9755
9756             offset++;
9757         }
9758     }
9759     
9760     /* now some housekeeping stuff */
9761     if (aop) {
9762         /* we had to allocate for this iCode */
9763         pic16_freeAsmop(NULL,aop,ic,TRUE);
9764     } else { 
9765         /* we did not allocate which means left
9766            already in a pointer register, then
9767            if size > 0 && this could be used again
9768            we have to point it back to where it 
9769            belongs */
9770         if (AOP_SIZE(right) > 1 &&
9771             !OP_SYMBOL(result)->remat &&
9772             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9773               ic->depth )) {
9774             int size = AOP_SIZE(right) - 1;
9775             while (size--)
9776                 pic16_emitcode("dec","%s",rname);
9777         }
9778     }
9779
9780     /* done */
9781     pic16_freeAsmop(right,NULL,ic,TRUE);
9782     
9783         
9784 }
9785
9786 /*-----------------------------------------------------------------*/
9787 /* genFarPointerSet - set value from far space                     */
9788 /*-----------------------------------------------------------------*/
9789 static void genFarPointerSet (operand *right,
9790                               operand *result, iCode *ic)
9791 {
9792     int size, offset ;
9793     sym_link *retype = getSpec(operandType(right));
9794
9795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9796     pic16_aopOp(result,ic,FALSE);
9797
9798     /* if the operand is already in dptr 
9799     then we do nothing else we move the value to dptr */
9800     if (AOP_TYPE(result) != AOP_STR) {
9801         /* if this is remateriazable */
9802         if (AOP_TYPE(result) == AOP_IMMD)
9803             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9804         else { /* we need to get it byte by byte */
9805             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9806             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9807             if (options.model == MODEL_FLAT24)
9808             {
9809                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9810             }
9811         }
9812     }
9813     /* so dptr know contains the address */
9814     pic16_freeAsmop(result,NULL,ic,TRUE);
9815     pic16_aopOp(right,ic,FALSE);
9816
9817     /* if bit then unpack */
9818     if (IS_BITFIELD(retype)) 
9819         genPackBits(retype,right,"dptr",FPOINTER);
9820     else {
9821         size = AOP_SIZE(right);
9822         offset = 0 ;
9823
9824         while (size--) {
9825             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9826             MOVA(l);
9827             pic16_emitcode("movx","@dptr,a");
9828             if (size)
9829                 pic16_emitcode("inc","dptr");
9830         }
9831     }
9832
9833     pic16_freeAsmop(right,NULL,ic,TRUE);
9834 }
9835
9836 /*-----------------------------------------------------------------*/
9837 /* genGenPointerSet - set value from generic pointer space         */
9838 /*-----------------------------------------------------------------*/
9839 static void genGenPointerSet (operand *right,
9840                               operand *result, iCode *ic)
9841 {
9842         int i, size, offset, lit;
9843         sym_link *retype = getSpec(operandType(right));
9844
9845         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9846
9847         pic16_aopOp(result,ic,FALSE);
9848         pic16_aopOp(right,ic,FALSE);
9849         size = AOP_SIZE(right);
9850         offset = 0;
9851
9852         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9853
9854         /* if the operand is already in dptr 
9855                 then we do nothing else we move the value to dptr */
9856         if (AOP_TYPE(result) != AOP_STR) {
9857                 /* if this is remateriazable */
9858                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9859                 // WARNING: anythig until "else" is untested!
9860                 if (AOP_TYPE(result) == AOP_IMMD) {
9861                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9862                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9863                         // load FSR0 from immediate
9864                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9865                         offset = 0;
9866                         while(size--) {
9867                                 if(size) {
9868                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9869                                 } else {
9870                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9871                                 }
9872                                 offset++;
9873                         }
9874                         goto release;
9875                 }
9876                 else { /* we need to get it byte by byte */
9877                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9878                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9879
9880                         // set up FSR0 with address of result
9881                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9882                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9883
9884                         /* hack hack! see if this the FSR. If so don't load W */
9885                         if(AOP_TYPE(right) != AOP_ACC) {
9886
9887                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9888
9889                                 if(AOP_TYPE(right) == AOP_LIT)
9890                                 {
9891                                         // copy literal
9892                                         // note: pic16_popGet handles sign extension
9893                                         for(i=0;i<size;i++) {
9894                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
9895                                                 if(i < size-1)
9896                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
9897                                                 else
9898                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9899                                         }
9900                                 } else {
9901                                         // copy regs
9902
9903                                         for(i=0;i<size;i++) {
9904                                                 if(i < size-1)
9905                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9906                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
9907                                                 else
9908                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9909                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
9910                                         }
9911                                 }
9912                                 goto release;
9913                         } 
9914                         // right = ACC
9915                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9916                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9917                         goto release;
9918         } // if (AOP_TYPE(result) != AOP_IMMD)
9919
9920         } // if (AOP_TYPE(result) != AOP_STR)
9921         /* so dptr know contains the address */
9922
9923
9924         /* if bit then unpack */
9925         if (IS_BITFIELD(retype)) 
9926                 genPackBits(retype,right,"dptr",GPOINTER);
9927         else {
9928                 size = AOP_SIZE(right);
9929                 offset = 0 ;
9930
9931                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9932
9933                 // set up FSR0 with address of result
9934                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9935                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9936         
9937                 while (size--) {
9938                         if (AOP_TYPE(right) == AOP_LIT) {
9939                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9940                                 if (size) {
9941                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9942                                 } else {
9943                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9944                                 }
9945                         } else { // no literal
9946                                 if(size) {
9947                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9948                                 } else {
9949                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9950                                 }
9951                         }
9952                         offset++;
9953                 }
9954         }
9955
9956         release:
9957         pic16_freeAsmop(right,NULL,ic,TRUE);
9958         pic16_freeAsmop(result,NULL,ic,TRUE);
9959 }
9960
9961 /*-----------------------------------------------------------------*/
9962 /* genPointerSet - stores the value into a pointer location        */
9963 /*-----------------------------------------------------------------*/
9964 static void genPointerSet (iCode *ic)
9965 {    
9966     operand *right, *result ;
9967     sym_link *type, *etype;
9968     int p_type;
9969
9970     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9971
9972     right = IC_RIGHT(ic);
9973     result = IC_RESULT(ic) ;
9974
9975     /* depending on the type of pointer we need to
9976     move it to the correct pointer register */
9977     type = operandType(result);
9978     etype = getSpec(type);
9979     /* if left is of type of pointer then it is simple */
9980     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9981         p_type = DCL_TYPE(type);
9982     }
9983     else {
9984         /* we have to go by the storage class */
9985         p_type = PTR_TYPE(SPEC_OCLS(etype));
9986
9987 /*      if (SPEC_OCLS(etype)->codesp ) { */
9988 /*          p_type = CPOINTER ;  */
9989 /*      } */
9990 /*      else */
9991 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9992 /*              p_type = FPOINTER ; */
9993 /*          else */
9994 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9995 /*                  p_type = PPOINTER ; */
9996 /*              else */
9997 /*                  if (SPEC_OCLS(etype) == idata ) */
9998 /*                      p_type = IPOINTER ; */
9999 /*                  else */
10000 /*                      p_type = POINTER ; */
10001     }
10002
10003     /* now that we have the pointer type we assign
10004     the pointer values */
10005     switch (p_type) {
10006
10007     case POINTER:
10008     case IPOINTER:
10009         genNearPointerSet (right,result,ic);
10010         break;
10011
10012     case PPOINTER:
10013         genPagedPointerSet (right,result,ic);
10014         break;
10015
10016     case FPOINTER:
10017         genFarPointerSet (right,result,ic);
10018         break;
10019
10020     case GPOINTER:
10021         genGenPointerSet (right,result,ic);
10022         break;
10023
10024     default:
10025       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10026               "genPointerSet: illegal pointer type");
10027     }
10028 }
10029
10030 /*-----------------------------------------------------------------*/
10031 /* genIfx - generate code for Ifx statement                        */
10032 /*-----------------------------------------------------------------*/
10033 static void genIfx (iCode *ic, iCode *popIc)
10034 {
10035   operand *cond = IC_COND(ic);
10036   int isbit =0;
10037
10038   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10039
10040   pic16_aopOp(cond,ic,FALSE);
10041
10042   /* get the value into acc */
10043   if (AOP_TYPE(cond) != AOP_CRY)
10044     pic16_toBoolean(cond);
10045   else
10046     isbit = 1;
10047   /* the result is now in the accumulator */
10048   pic16_freeAsmop(cond,NULL,ic,TRUE);
10049
10050   /* if there was something to be popped then do it */
10051   if (popIc)
10052     genIpop(popIc);
10053
10054   /* if the condition is  a bit variable */
10055   if (isbit && IS_ITEMP(cond) && 
10056       SPIL_LOC(cond)) {
10057     genIfxJump(ic,SPIL_LOC(cond)->rname);
10058     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10059   }
10060   else {
10061     if (isbit && !IS_ITEMP(cond))
10062       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10063     else
10064       genIfxJump(ic,"a");
10065   }
10066   ic->generated = 1;
10067
10068 }
10069
10070 /*-----------------------------------------------------------------*/
10071 /* genAddrOf - generates code for address of                       */
10072 /*-----------------------------------------------------------------*/
10073 static void genAddrOf (iCode *ic)
10074 {
10075   operand *result, *left;
10076   int size;
10077   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10078   pCodeOp *pcop0, *pcop1, *pcop2;
10079
10080         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10081
10082         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10083         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10084
10085         sym = OP_SYMBOL( left );
10086
10087         size = AOP_SIZE(IC_RESULT(ic));
10088
10089         if(pic16_debug_verbose) {
10090                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10091                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10092         }
10093         
10094         /* Assume that what we want the address of is in data space
10095          * since there is no stack on the PIC, yet! -- VR */
10096         /* low */
10097         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10098
10099         /* high */
10100         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10101         
10102         /* upper */
10103         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10104         
10105
10106         if (size == 3) {
10107                 pic16_emitpcode(POC_MOVLW, pcop0);
10108                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10109                 pic16_emitpcode(POC_MOVLW, pcop1);
10110                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10111                 pic16_emitpcode(POC_MOVLW, pcop2);
10112                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10113         } else
10114         if (size == 2) {
10115                 pic16_emitpcode(POC_MOVLW, pcop0);
10116                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10117                 pic16_emitpcode(POC_MOVLW, pcop1);
10118                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10119         } else {
10120                 pic16_emitpcode(POC_MOVLW, pcop0);
10121                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10122         }
10123
10124         pic16_freeAsmop(result,NULL,ic,TRUE);
10125         pic16_freeAsmop(left, NULL, ic, FALSE);
10126 }
10127
10128
10129 #if 0
10130 /*-----------------------------------------------------------------*/
10131 /* genFarFarAssign - assignment when both are in far space         */
10132 /*-----------------------------------------------------------------*/
10133 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10134 {
10135     int size = AOP_SIZE(right);
10136     int offset = 0;
10137     char *l ;
10138     /* first push the right side on to the stack */
10139     while (size--) {
10140         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10141         MOVA(l);
10142         pic16_emitcode ("push","acc");
10143     }
10144     
10145     pic16_freeAsmop(right,NULL,ic,FALSE);
10146     /* now assign DPTR to result */
10147     pic16_aopOp(result,ic,FALSE);
10148     size = AOP_SIZE(result);
10149     while (size--) {
10150         pic16_emitcode ("pop","acc");
10151         pic16_aopPut(AOP(result),"a",--offset);
10152     }
10153     pic16_freeAsmop(result,NULL,ic,FALSE);
10154         
10155 }
10156 #endif
10157
10158 /*-----------------------------------------------------------------*/
10159 /* genAssign - generate code for assignment                        */
10160 /*-----------------------------------------------------------------*/
10161 static void genAssign (iCode *ic)
10162 {
10163   operand *result, *right;
10164   int size, offset,know_W;
10165   unsigned long lit = 0L;
10166
10167   result = IC_RESULT(ic);
10168   right  = IC_RIGHT(ic) ;
10169
10170   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10171   
10172   /* if they are the same */
10173   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10174     return ;
10175
10176   pic16_aopOp(right,ic,FALSE);
10177   pic16_aopOp(result,ic,TRUE);
10178
10179   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10180
10181   /* if they are the same registers */
10182   if (pic16_sameRegs(AOP(right),AOP(result)))
10183     goto release;
10184
10185   /* if the result is a bit */
10186   if (AOP_TYPE(result) == AOP_CRY) {
10187     /* if the right size is a literal then
10188        we know what the value is */
10189     if (AOP_TYPE(right) == AOP_LIT) {
10190           
10191       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10192                   pic16_popGet(AOP(result),0));
10193
10194       if (((int) operandLitValue(right))) 
10195         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10196                        AOP(result)->aopu.aop_dir,
10197                        AOP(result)->aopu.aop_dir);
10198       else
10199         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10200                        AOP(result)->aopu.aop_dir,
10201                        AOP(result)->aopu.aop_dir);
10202       goto release;
10203     }
10204
10205     /* the right is also a bit variable */
10206     if (AOP_TYPE(right) == AOP_CRY) {
10207       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10208       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10209       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10210
10211       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10212                      AOP(result)->aopu.aop_dir,
10213                      AOP(result)->aopu.aop_dir);
10214       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10215                      AOP(right)->aopu.aop_dir,
10216                      AOP(right)->aopu.aop_dir);
10217       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10218                      AOP(result)->aopu.aop_dir,
10219                      AOP(result)->aopu.aop_dir);
10220       goto release ;
10221     }
10222
10223     /* we need to or */
10224     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10225     pic16_toBoolean(right);
10226     emitSKPZ;
10227     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10228     //pic16_aopPut(AOP(result),"a",0);
10229     goto release ;
10230   }
10231
10232   /* bit variables done */
10233   /* general case */
10234   size = AOP_SIZE(result);
10235   offset = 0 ;
10236   if(AOP_TYPE(right) == AOP_LIT)
10237     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10238
10239 /* VR - What is this?! */
10240   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10241   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10242     if(aopIdx(AOP(result),0) == 4) {
10243   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10244       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10245       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10246       goto release;
10247     } else
10248       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10249   }
10250
10251   know_W=-1;
10252   while (size--) {
10253   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10254     if(AOP_TYPE(right) == AOP_LIT) {
10255       if(lit&0xff) {
10256         if(know_W != (lit&0xff))
10257           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10258         know_W = lit&0xff;
10259         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10260       } else
10261         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10262
10263       lit >>= 8;
10264
10265     } else if (AOP_TYPE(right) == AOP_CRY) {
10266       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10267       if(offset == 0) {
10268         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10269         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10270       }
10271     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10272         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10273         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10274     } else {
10275   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10276
10277 #if 1
10278         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10279            normally should work, but mind that the W register live range
10280            is not checked, so if the code generator assumes that the W
10281            is already loaded after such a pair, wrong code will be generated.
10282            
10283            Checking the live range is the next step.
10284            This is experimental code yet and has not been fully tested yet.
10285            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10286            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10287            
10288         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10289 #else   
10290         /* This is the old code, which is assumed(?!) that works fine(!?) */
10291
10292         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10293         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10294 #endif
10295     }
10296             
10297     offset++;
10298   }
10299
10300     
10301  release:
10302   pic16_freeAsmop (right,NULL,ic,FALSE);
10303   pic16_freeAsmop (result,NULL,ic,TRUE);
10304 }   
10305
10306 /*-----------------------------------------------------------------*/
10307 /* genJumpTab - generates code for jump table                       */
10308 /*-----------------------------------------------------------------*/
10309 static void genJumpTab (iCode *ic)
10310 {
10311     symbol *jtab;
10312     char *l;
10313
10314     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10315
10316     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10317     /* get the condition into accumulator */
10318     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10319     MOVA(l);
10320     /* multiply by three */
10321     pic16_emitcode("add","a,acc");
10322     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10323
10324     jtab = newiTempLabel(NULL);
10325     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10326     pic16_emitcode("jmp","@a+dptr");
10327     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10328
10329     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10330     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10331     emitSKPNC;
10332     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10333     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10334     pic16_emitpLabel(jtab->key);
10335
10336     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10337
10338     /* now generate the jump labels */
10339     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10340          jtab = setNextItem(IC_JTLABELS(ic))) {
10341         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10342         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10343         
10344     }
10345
10346 }
10347
10348 /*-----------------------------------------------------------------*/
10349 /* genMixedOperation - gen code for operators between mixed types  */
10350 /*-----------------------------------------------------------------*/
10351 /*
10352   TSD - Written for the PIC port - but this unfortunately is buggy.
10353   This routine is good in that it is able to efficiently promote 
10354   types to different (larger) sizes. Unfortunately, the temporary
10355   variables that are optimized out by this routine are sometimes
10356   used in other places. So until I know how to really parse the 
10357   iCode tree, I'm going to not be using this routine :(.
10358 */
10359 static int genMixedOperation (iCode *ic)
10360 {
10361 #if 0
10362   operand *result = IC_RESULT(ic);
10363   sym_link *ctype = operandType(IC_LEFT(ic));
10364   operand *right = IC_RIGHT(ic);
10365   int ret = 0;
10366   int big,small;
10367   int offset;
10368
10369   iCode *nextic;
10370   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10371
10372   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10373
10374   nextic = ic->next;
10375   if(!nextic)
10376     return 0;
10377
10378   nextright = IC_RIGHT(nextic);
10379   nextleft  = IC_LEFT(nextic);
10380   nextresult = IC_RESULT(nextic);
10381
10382   pic16_aopOp(right,ic,FALSE);
10383   pic16_aopOp(result,ic,FALSE);
10384   pic16_aopOp(nextright,  nextic, FALSE);
10385   pic16_aopOp(nextleft,   nextic, FALSE);
10386   pic16_aopOp(nextresult, nextic, FALSE);
10387
10388   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10389
10390     operand *t = right;
10391     right = nextright;
10392     nextright = t; 
10393
10394     pic16_emitcode(";remove right +","");
10395
10396   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10397 /*
10398     operand *t = right;
10399     right = nextleft;
10400     nextleft = t; 
10401 */
10402     pic16_emitcode(";remove left +","");
10403   } else
10404     return 0;
10405
10406   big = AOP_SIZE(nextleft);
10407   small = AOP_SIZE(nextright);
10408
10409   switch(nextic->op) {
10410
10411   case '+':
10412     pic16_emitcode(";optimize a +","");
10413     /* if unsigned or not an integral type */
10414     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10415       pic16_emitcode(";add a bit to something","");
10416     } else {
10417
10418       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10419
10420       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10421         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10422         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10423       } else
10424         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10425
10426       offset = 0;
10427       while(--big) {
10428
10429         offset++;
10430
10431         if(--small) {
10432           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10433             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10434             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10435           }
10436
10437           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10438           emitSKPNC;
10439           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10440                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10441                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10442           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10443           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10444
10445         } else {
10446           pic16_emitcode("rlf","known_zero,w");
10447
10448           /*
10449             if right is signed
10450               btfsc  right,7
10451                addlw ff
10452           */
10453           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10454             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10455             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10456           } else {
10457             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10458           }
10459         }
10460       }
10461       ret = 1;
10462     }
10463   }
10464   ret = 1;
10465
10466 release:
10467   pic16_freeAsmop(right,NULL,ic,TRUE);
10468   pic16_freeAsmop(result,NULL,ic,TRUE);
10469   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10470   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10471   if(ret)
10472     nextic->generated = 1;
10473
10474   return ret;
10475 #else
10476   return 0;
10477 #endif
10478 }
10479 /*-----------------------------------------------------------------*/
10480 /* genCast - gen code for casting                                  */
10481 /*-----------------------------------------------------------------*/
10482 static void genCast (iCode *ic)
10483 {
10484   operand *result = IC_RESULT(ic);
10485   sym_link *ctype = operandType(IC_LEFT(ic));
10486   sym_link *rtype = operandType(IC_RIGHT(ic));
10487   operand *right = IC_RIGHT(ic);
10488   int size, offset ;
10489
10490         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10491         /* if they are equivalent then do nothing */
10492         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10493                 return ;
10494
10495         pic16_aopOp(right,ic,FALSE) ;
10496         pic16_aopOp(result,ic,FALSE);
10497
10498         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10499
10500         /* if the result is a bit */
10501         if (AOP_TYPE(result) == AOP_CRY) {
10502         
10503                 /* if the right size is a literal then
10504                  * we know what the value is */
10505                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10506
10507                 if (AOP_TYPE(right) == AOP_LIT) {
10508                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10509                                 pic16_popGet(AOP(result),0));
10510
10511                         if (((int) operandLitValue(right))) 
10512                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10513                                         AOP(result)->aopu.aop_dir,
10514                                         AOP(result)->aopu.aop_dir);
10515                         else
10516                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10517                                         AOP(result)->aopu.aop_dir,
10518                                         AOP(result)->aopu.aop_dir);
10519                         goto release;
10520                 }
10521
10522                 /* the right is also a bit variable */
10523                 if (AOP_TYPE(right) == AOP_CRY) {
10524                         emitCLRC;
10525                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10526
10527                         pic16_emitcode("clrc","");
10528                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10529                                 AOP(right)->aopu.aop_dir,
10530                                 AOP(right)->aopu.aop_dir);
10531                         pic16_aopPut(AOP(result),"c",0);
10532                         goto release ;
10533                 }
10534
10535                 /* we need to or */
10536                 if (AOP_TYPE(right) == AOP_REG) {
10537                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10538                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10539                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10540                 }
10541                 pic16_toBoolean(right);
10542                 pic16_aopPut(AOP(result),"a",0);
10543                 goto release ;
10544         }
10545
10546         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10547           int offset = 1;
10548
10549                 size = AOP_SIZE(result);
10550
10551                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10552
10553                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10554                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10555                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10556
10557                 while (size--)
10558                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10559
10560                 goto release;
10561         }
10562
10563         /* if they are the same size : or less */
10564         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10565
10566                 /* if they are in the same place */
10567                 if (pic16_sameRegs(AOP(right),AOP(result)))
10568                         goto release;
10569
10570                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10571 #if 0
10572                 if (IS_PTR_CONST(rtype))
10573 #else
10574                 if (IS_CODEPTR(rtype))
10575 #endif
10576                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10577
10578 #if 0
10579                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10580 #else
10581                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10582 #endif
10583                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10584
10585 #if 0
10586                 if(AOP_TYPE(right) == AOP_IMMD) {
10587                   pCodeOp *pcop0, *pcop1, *pcop2;
10588                   symbol *sym = OP_SYMBOL( right );
10589
10590                         size = AOP_SIZE(result);
10591                         /* low */
10592                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10593                         /* high */
10594                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10595                         /* upper */
10596                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10597         
10598                         if (size == 3) {
10599                                 pic16_emitpcode(POC_MOVLW, pcop0);
10600                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10601                                 pic16_emitpcode(POC_MOVLW, pcop1);
10602                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10603                                 pic16_emitpcode(POC_MOVLW, pcop2);
10604                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10605                         } else
10606                         if (size == 2) {
10607                                 pic16_emitpcode(POC_MOVLW, pcop0);
10608                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10609                                 pic16_emitpcode(POC_MOVLW, pcop1);
10610                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10611                         } else {
10612                                 pic16_emitpcode(POC_MOVLW, pcop0);
10613                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10614                         }
10615                 } else
10616 #endif
10617                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10618                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10619                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10620                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10621                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10622                         if(AOP_SIZE(result) <2)
10623                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10624                 } else {
10625                         /* if they in different places then copy */
10626                         size = AOP_SIZE(result);
10627                         offset = 0 ;
10628                         while (size--) {
10629                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10630                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10631                                 offset++;
10632                         }
10633                 }
10634                 goto release;
10635         }
10636
10637         /* if the result is of type pointer */
10638         if (IS_PTR(ctype)) {
10639           int p_type;
10640           sym_link *type = operandType(right);
10641           sym_link *etype = getSpec(type);
10642
10643                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10644
10645                 /* pointer to generic pointer */
10646                 if (IS_GENPTR(ctype)) {
10647                   char *l = zero;
10648             
10649                         if (IS_PTR(type)) 
10650                                 p_type = DCL_TYPE(type);
10651                         else {
10652                 /* we have to go by the storage class */
10653                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10654
10655 /*              if (SPEC_OCLS(etype)->codesp )  */
10656 /*                  p_type = CPOINTER ;  */
10657 /*              else */
10658 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10659 /*                      p_type = FPOINTER ; */
10660 /*                  else */
10661 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10662 /*                          p_type = PPOINTER; */
10663 /*                      else */
10664 /*                          if (SPEC_OCLS(etype) == idata ) */
10665 /*                              p_type = IPOINTER ; */
10666 /*                          else */
10667 /*                              p_type = POINTER ; */
10668             }
10669                 
10670             /* the first two bytes are known */
10671       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10672             size = GPTRSIZE - 1; 
10673             offset = 0 ;
10674             while (size--) {
10675               if(offset < AOP_SIZE(right)) {
10676       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10677                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10678                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10679                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10680                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10681                 } else { 
10682                   pic16_aopPut(AOP(result),
10683                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10684                          offset);
10685                 }
10686               } else 
10687                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10688               offset++;
10689             }
10690             /* the last byte depending on type */
10691             switch (p_type) {
10692             case IPOINTER:
10693             case POINTER:
10694                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10695                 break;
10696             case FPOINTER:
10697               pic16_emitcode(";BUG!? ","%d",__LINE__);
10698                 l = one;
10699                 break;
10700             case CPOINTER:
10701               pic16_emitcode(";BUG!? ","%d",__LINE__);
10702                 l = "#0x02";
10703                 break;                          
10704             case PPOINTER:
10705               pic16_emitcode(";BUG!? ","%d",__LINE__);
10706                 l = "#0x03";
10707                 break;
10708                 
10709             default:
10710                 /* this should never happen */
10711                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10712                        "got unknown pointer type");
10713                 exit(1);
10714             }
10715             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10716             goto release ;
10717         }
10718         
10719         /* just copy the pointers */
10720         size = AOP_SIZE(result);
10721         offset = 0 ;
10722         while (size--) {
10723             pic16_aopPut(AOP(result),
10724                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10725                    offset);
10726             offset++;
10727         }
10728         goto release ;
10729     }
10730     
10731
10732
10733     /* so we now know that the size of destination is greater
10734     than the size of the source.
10735     Now, if the next iCode is an operator then we might be
10736     able to optimize the operation without performing a cast.
10737     */
10738     if(genMixedOperation(ic))
10739       goto release;
10740
10741     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10742     
10743     /* we move to result for the size of source */
10744     size = AOP_SIZE(right);
10745     offset = 0 ;
10746     while (size--) {
10747       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10748       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10749       offset++;
10750     }
10751
10752     /* now depending on the sign of the destination */
10753     size = AOP_SIZE(result) - AOP_SIZE(right);
10754     /* if unsigned or not an integral type */
10755     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10756       while (size--)
10757         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10758     } else {
10759       /* we need to extend the sign :( */
10760
10761       if(size == 1) {
10762         /* Save one instruction of casting char to int */
10763         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10764         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10765         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10766       } else {
10767         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10768
10769         if(offset)
10770           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10771         else
10772           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10773         
10774         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10775
10776         while (size--)
10777           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10778       }
10779     }
10780
10781 release:
10782     pic16_freeAsmop(right,NULL,ic,TRUE);
10783     pic16_freeAsmop(result,NULL,ic,TRUE);
10784
10785 }
10786
10787 /*-----------------------------------------------------------------*/
10788 /* genDjnz - generate decrement & jump if not zero instrucion      */
10789 /*-----------------------------------------------------------------*/
10790 static int genDjnz (iCode *ic, iCode *ifx)
10791 {
10792     symbol *lbl, *lbl1;
10793     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10794
10795     if (!ifx)
10796         return 0;
10797     
10798     /* if the if condition has a false label
10799        then we cannot save */
10800     if (IC_FALSE(ifx))
10801         return 0;
10802
10803     /* if the minus is not of the form 
10804        a = a - 1 */
10805     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10806         !IS_OP_LITERAL(IC_RIGHT(ic)))
10807         return 0;
10808
10809     if (operandLitValue(IC_RIGHT(ic)) != 1)
10810         return 0;
10811
10812     /* if the size of this greater than one then no
10813        saving */
10814     if (getSize(operandType(IC_RESULT(ic))) > 1)
10815         return 0;
10816
10817     /* otherwise we can save BIG */
10818     lbl = newiTempLabel(NULL);
10819     lbl1= newiTempLabel(NULL);
10820
10821     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10822     
10823     if (IS_AOP_PREG(IC_RESULT(ic))) {
10824         pic16_emitcode("dec","%s",
10825                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10826         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10827         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10828     } else {    
10829
10830
10831       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10832       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10833
10834       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10835       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10836
10837     }
10838 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10839 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10840 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10841 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10842
10843     
10844     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10845     ifx->generated = 1;
10846     return 1;
10847 }
10848
10849 /*-----------------------------------------------------------------*/
10850 /* genReceive - generate code for a receive iCode                  */
10851 /*-----------------------------------------------------------------*/
10852 static void genReceive (iCode *ic)
10853 {    
10854         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10855
10856         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10857                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10858                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10859
10860           int size = getSize(operandType(IC_RESULT(ic)));
10861           int offset =  pic16_fReturnSizePic - size;
10862
10863                 while (size--) {
10864                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10865                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10866                         offset++;
10867                 }
10868
10869                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10870
10871                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10872                 size = AOP_SIZE(IC_RESULT(ic));
10873                 offset = 0;
10874                 while (size--) {
10875                         pic16_emitcode ("pop","acc");
10876                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10877                 }
10878         } else {
10879                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10880
10881                 _G.accInUse++;
10882                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10883                 _G.accInUse--;
10884                 assignResultValue(IC_RESULT(ic), 0);
10885         }
10886
10887         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10888 }
10889
10890 /*-----------------------------------------------------------------*/
10891 /* genDummyRead - generate code for dummy read of volatiles        */
10892 /*-----------------------------------------------------------------*/
10893 static void
10894 genDummyRead (iCode * ic)
10895 {
10896   pic16_emitcode ("; genDummyRead","");
10897   pic16_emitcode ("; not implemented","");
10898
10899   ic = ic;
10900 }
10901
10902 /*-----------------------------------------------------------------*/
10903 /* genpic16Code - generate code for pic16 based controllers        */
10904 /*-----------------------------------------------------------------*/
10905 /*
10906  * At this point, ralloc.c has gone through the iCode and attempted
10907  * to optimize in a way suitable for a PIC. Now we've got to generate
10908  * PIC instructions that correspond to the iCode.
10909  *
10910  * Once the instructions are generated, we'll pass through both the
10911  * peep hole optimizer and the pCode optimizer.
10912  *-----------------------------------------------------------------*/
10913
10914 void genpic16Code (iCode *lic)
10915 {
10916     iCode *ic;
10917     int cln = 0;
10918
10919     lineHead = lineCurr = NULL;
10920
10921     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10922     pic16_addpBlock(pb);
10923
10924 #if 0
10925     /* if debug information required */
10926     if (options.debug && currFunc) {
10927       if (currFunc) {
10928         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10929         _G.debugLine = 1;
10930         if (IS_STATIC(currFunc->etype)) {
10931           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10932           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10933         } else {
10934           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10935           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10936         }
10937         _G.debugLine = 0;
10938       }
10939     }
10940 #endif
10941
10942     for (ic = lic ; ic ; ic = ic->next ) {
10943
10944       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10945         if ( cln != ic->lineno ) {
10946             if ( options.debug ) {
10947                 _G.debugLine = 1;
10948                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10949                          FileBaseName(ic->filename),ic->lineno,
10950                          ic->level,ic->block);
10951                 _G.debugLine = 0;
10952             }
10953             
10954             if(!options.noCcodeInAsm) {
10955                 pic16_addpCode2pBlock(pb,
10956                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10957                                 printCLine(ic->filename, ic->lineno)));
10958             }
10959
10960             cln = ic->lineno ;
10961         }
10962         
10963         if(options.iCodeInAsm) {
10964                 /* insert here code to print iCode as comment */
10965                 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10966         }
10967         
10968         /* if the result is marked as
10969            spilt and rematerializable or code for
10970            this has already been generated then
10971            do nothing */
10972         if (resultRemat(ic) || ic->generated ) 
10973             continue ;
10974         
10975         /* depending on the operation */
10976         switch (ic->op) {
10977         case '!' :
10978             pic16_genNot(ic);
10979             break;
10980             
10981         case '~' :
10982             pic16_genCpl(ic);
10983             break;
10984             
10985         case UNARYMINUS:
10986             genUminus (ic);
10987             break;
10988             
10989         case IPUSH:
10990             genIpush (ic);
10991             break;
10992             
10993         case IPOP:
10994             /* IPOP happens only when trying to restore a 
10995                spilt live range, if there is an ifx statement
10996                following this pop then the if statement might
10997                be using some of the registers being popped which
10998                would destroy the contents of the register so
10999                we need to check for this condition and handle it */
11000             if (ic->next            && 
11001                 ic->next->op == IFX &&
11002                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11003                 genIfx (ic->next,ic);
11004             else
11005                 genIpop (ic);
11006             break; 
11007             
11008         case CALL:
11009             genCall (ic);
11010             break;
11011             
11012         case PCALL:
11013             genPcall (ic);
11014             break;
11015             
11016         case FUNCTION:
11017             genFunction (ic);
11018             break;
11019             
11020         case ENDFUNCTION:
11021             genEndFunction (ic);
11022             break;
11023             
11024         case RETURN:
11025             genRet (ic);
11026             break;
11027             
11028         case LABEL:
11029             genLabel (ic);
11030             break;
11031             
11032         case GOTO:
11033             genGoto (ic);
11034             break;
11035             
11036         case '+' :
11037             pic16_genPlus (ic) ;
11038             break;
11039             
11040         case '-' :
11041             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11042                 pic16_genMinus (ic);
11043             break;
11044             
11045         case '*' :
11046             genMult (ic);
11047             break;
11048             
11049         case '/' :
11050             genDiv (ic) ;
11051             break;
11052             
11053         case '%' :
11054             genMod (ic);
11055             break;
11056             
11057         case '>' :
11058             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11059             break;
11060             
11061         case '<' :
11062             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11063             break;
11064             
11065         case LE_OP:
11066         case GE_OP:
11067         case NE_OP:
11068             
11069             /* note these two are xlated by algebraic equivalence
11070                during parsing SDCC.y */
11071             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11072                    "got '>=' or '<=' shouldn't have come here");
11073             break;      
11074             
11075         case EQ_OP:
11076             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11077             break;          
11078             
11079         case AND_OP:
11080             genAndOp (ic);
11081             break;
11082             
11083         case OR_OP:
11084             genOrOp (ic);
11085             break;
11086             
11087         case '^' :
11088             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11089             break;
11090             
11091         case '|' :
11092                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11093             break;
11094             
11095         case BITWISEAND:
11096             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11097             break;
11098             
11099         case INLINEASM:
11100             genInline (ic);
11101             break;
11102             
11103         case RRC:
11104             genRRC (ic);
11105             break;
11106             
11107         case RLC:
11108             genRLC (ic);
11109             break;
11110             
11111         case GETHBIT:
11112             genGetHbit (ic);
11113             break;
11114             
11115         case LEFT_OP:
11116             genLeftShift (ic);
11117             break;
11118             
11119         case RIGHT_OP:
11120             genRightShift (ic);
11121             break;
11122             
11123         case GET_VALUE_AT_ADDRESS:
11124             genPointerGet(ic);
11125             break;
11126             
11127         case '=' :
11128             if (POINTER_SET(ic))
11129                 genPointerSet(ic);
11130             else
11131                 genAssign(ic);
11132             break;
11133             
11134         case IFX:
11135             genIfx (ic,NULL);
11136             break;
11137             
11138         case ADDRESS_OF:
11139             genAddrOf (ic);
11140             break;
11141             
11142         case JUMPTABLE:
11143             genJumpTab (ic);
11144             break;
11145             
11146         case CAST:
11147             genCast (ic);
11148             break;
11149             
11150         case RECEIVE:
11151             genReceive(ic);
11152             break;
11153             
11154         case SEND:
11155             addSet(&_G.sendSet,ic);
11156             break;
11157
11158         case DUMMY_READ_VOLATILE:
11159           genDummyRead (ic);
11160           break;
11161
11162         default :
11163             ic = ic;
11164         }
11165     }
11166
11167
11168     /* now we are ready to call the
11169        peep hole optimizer */
11170     if (!options.nopeep) {
11171       peepHole (&lineHead);
11172     }
11173     /* now do the actual printing */
11174     printLine (lineHead,codeOutFile);
11175
11176 #ifdef PCODE_DEBUG
11177     DFPRINTF((stderr,"printing pBlock\n\n"));
11178     pic16_printpBlock(stdout,pb);
11179 #endif
11180
11181     return;
11182 }
11183