* src/pic16/device.c (checkAddSym): NEW, adds a symbol to set while
[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;
5153
5154   unsigned long lit = 0L;
5155   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5156   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5157   if(result)
5158     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5159   resolveIfx(&rIfx,ifx);
5160   lbl =  newiTempLabel(NULL);
5161
5162
5163   /* if the left side is a literal or 
5164      if the right is in a pointer register and left 
5165      is not */
5166   if ((AOP_TYPE(left) == AOP_LIT) || 
5167       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5168     operand *t = right;
5169     right = left;
5170     left = t;
5171   }
5172   if(AOP_TYPE(right) == AOP_LIT)
5173     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5174
5175   /* if the right side is a literal then anything goes */
5176   if (AOP_TYPE(right) == AOP_LIT &&
5177       AOP_TYPE(left) != AOP_DIR ) {
5178     switch(size) {
5179     case 2:
5180       genc16bit2lit(left, lit, 0);
5181       emitSKPNZ;
5182       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5183       break;
5184     default:
5185       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5186       while (size--) {
5187         if(lit & 0xff) {
5188           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5189           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5190         } else {
5191           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5192         }
5193
5194         emitSKPNZ;
5195         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5196         offset++;
5197         if(res_offset < res_size-1)
5198           res_offset++;
5199         lit >>= 8;
5200       }
5201       break;
5202     }
5203   }
5204
5205   /* if the right side is in a register or in direct space or
5206      if the left is a pointer register & right is not */    
5207   else if (AOP_TYPE(right) == AOP_REG ||
5208            AOP_TYPE(right) == AOP_DIR || 
5209            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5210            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5211     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5212     int lbl_key = lbl->key;
5213
5214     if(result) {
5215       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5216       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5217     }else {
5218       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5219       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5220               __FUNCTION__,__LINE__);
5221       return;
5222     }
5223
5224 /*     switch(size) { */
5225 /*     case 2: */
5226 /*       genc16bit2lit(left, lit, 0); */
5227 /*       emitSKPNZ; */
5228 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5229 /*       break; */
5230 /*     default: */
5231     while (size--) {
5232       int emit_skip=1;
5233       if((AOP_TYPE(left) == AOP_DIR) && 
5234          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5235
5236         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5237         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5238
5239       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5240             
5241         switch (lit & 0xff) {
5242         case 0:
5243           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5244           break;
5245         case 1:
5246           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5247           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5248           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5249           emit_skip=0;
5250           break;
5251         case 0xff:
5252           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5253           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5254           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5255           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5256           emit_skip=0;
5257           break;
5258         default:
5259           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5260           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5261         }
5262         lit >>= 8;
5263
5264       } else {
5265         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5266       }
5267       if(emit_skip) {
5268         if(AOP_TYPE(result) == AOP_CRY) {
5269           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5270           if(rIfx.condition)
5271             emitSKPNZ;
5272           else
5273             emitSKPZ;
5274           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5275         } else {
5276           /* fix me. probably need to check result size too */
5277           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5278           if(rIfx.condition)
5279             emitSKPZ;
5280           else
5281             emitSKPNZ;
5282           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5283           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5284         }
5285         if(ifx)
5286           ifx->generated=1;
5287       }
5288       emit_skip++;
5289       offset++;
5290       if(res_offset < res_size-1)
5291         res_offset++;
5292     }
5293 /*       break; */
5294 /*     } */
5295   } else if(AOP_TYPE(right) == AOP_REG &&
5296             AOP_TYPE(left) != AOP_DIR){
5297
5298     while(size--) {
5299       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5300       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5301       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5302       if(rIfx.condition)
5303         emitSKPNZ;
5304       else
5305         emitSKPZ;
5306       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5307       offset++;
5308       if(res_offset < res_size-1)
5309         res_offset++;
5310     }
5311       
5312   }else{
5313     /* right is a pointer reg need both a & b */
5314     while(size--) {
5315       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5316       if(strcmp(l,"b"))
5317         pic16_emitcode("mov","b,%s",l);
5318       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5319       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5320       offset++;
5321     }
5322   }
5323
5324   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5325   if(!rIfx.condition)
5326     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5327
5328   pic16_emitpLabel(lbl->key);
5329
5330   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5331
5332   if(ifx)
5333     ifx->generated = 1;
5334 }
5335
5336 #if 0
5337 /*-----------------------------------------------------------------*/
5338 /* gencjne - compare and jump if not equal                         */
5339 /*-----------------------------------------------------------------*/
5340 static void gencjne(operand *left, operand *right, iCode *ifx)
5341 {
5342     symbol *tlbl  = newiTempLabel(NULL);
5343
5344     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5345     gencjneshort(left, right, lbl);
5346
5347     pic16_emitcode("mov","a,%s",one);
5348     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5349     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5350     pic16_emitcode("clr","a");
5351     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5352
5353     pic16_emitpLabel(lbl->key);
5354     pic16_emitpLabel(tlbl->key);
5355
5356 }
5357 #endif
5358
5359 /*-----------------------------------------------------------------*/
5360 /* genCmpEq - generates code for equal to                          */
5361 /*-----------------------------------------------------------------*/
5362 static void genCmpEq (iCode *ic, iCode *ifx)
5363 {
5364     operand *left, *right, *result;
5365     unsigned long lit = 0L;
5366     int size,offset=0;
5367     symbol *falselbl  = newiTempLabel(NULL);
5368
5369
5370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5371
5372     if(ifx)
5373       DEBUGpic16_emitcode ("; ifx is non-null","");
5374     else
5375       DEBUGpic16_emitcode ("; ifx is null","");
5376
5377     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5378     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5379     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5380
5381     size = max(AOP_SIZE(left),AOP_SIZE(right));
5382
5383     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5384
5385     /* if literal, literal on the right or 
5386     if the right is in a pointer register and left 
5387     is not */
5388     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5389         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5390       operand *tmp = right ;
5391       right = left;
5392       left = tmp;
5393     }
5394
5395
5396     if(ifx && !AOP_SIZE(result)){
5397         symbol *tlbl;
5398         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5399         /* if they are both bit variables */
5400         if (AOP_TYPE(left) == AOP_CRY &&
5401             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5402                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5403             if(AOP_TYPE(right) == AOP_LIT){
5404                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5405                 if(lit == 0L){
5406                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5407                     pic16_emitcode("cpl","c");
5408                 } else if(lit == 1L) {
5409                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5410                 } else {
5411                     pic16_emitcode("clr","c");
5412                 }
5413                 /* AOP_TYPE(right) == AOP_CRY */
5414             } else {
5415                 symbol *lbl = newiTempLabel(NULL);
5416                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5417                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5418                 pic16_emitcode("cpl","c");
5419                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5420             }
5421             /* if true label then we jump if condition
5422             supplied is true */
5423             tlbl = newiTempLabel(NULL);
5424             if ( IC_TRUE(ifx) ) {
5425                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5426                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5427             } else {
5428                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5429                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5430             }
5431             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5432
5433                 {
5434                 /* left and right are both bit variables, result is carry */
5435                         resolvedIfx rIfx;
5436               
5437                         resolveIfx(&rIfx,ifx);
5438
5439                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5440                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5441                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5442                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5443                         genSkipz2(&rIfx,0);
5444                 }
5445         } else {
5446
5447                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5448
5449                         /* They're not both bit variables. Is the right a literal? */
5450                         if(AOP_TYPE(right) == AOP_LIT) {
5451                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5452             
5453                         switch(size) {
5454
5455                                 case 1:
5456                                         switch(lit & 0xff) {
5457                                                 case 1:
5458                                                                 if ( IC_TRUE(ifx) ) {
5459                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5460                                                                         emitSKPNZ;
5461                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5462                                                                 } else {
5463                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5464                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5465                                                                 }
5466                                                                 break;
5467                                                 case 0xff:
5468                                                                 if ( IC_TRUE(ifx) ) {
5469                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5470                                                                         emitSKPNZ;
5471                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5472                                                                 } else {
5473                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5474                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5475                                                                 }
5476                                                                 break;
5477                                                 default:
5478                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5479                                                                 if(lit)
5480                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5481                                                                 genSkip(ifx,'z');
5482                                         } // switch lit
5483
5484
5485                                         /* end of size == 1 */
5486                                         break;
5487               
5488                                 case 2:
5489                                         genc16bit2lit(left,lit,offset);
5490                                         genSkip(ifx,'z');
5491                                         break;
5492                                         /* end of size == 2 */
5493
5494                                 default:
5495                                         /* size is 4 */
5496                                         if(lit==0) {
5497                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5498                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5499                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5500                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5501                                                 genSkip(ifx,'z');
5502                                         } else {
5503                                                 /* search for patterns that can be optimized */
5504
5505                                                 genc16bit2lit(left,lit,0);
5506                                                 lit >>= 16;
5507                                                 if(lit) {
5508                                                                 if(IC_TRUE(ifx))
5509                                                                 emitSKPZ; // if hi word unequal
5510                                                                 else
5511                                                                 emitSKPNZ; // if hi word equal
5512                                                                 // fail early
5513                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5514                                                         genc16bit2lit(left,lit,2);
5515                                                         genSkip(ifx,'z');
5516                                                 } else {
5517                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5518                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5519                                                         genSkip(ifx,'z');
5520                                                 }
5521                                         }
5522                                                 pic16_emitpLabel(falselbl->key);
5523                                                 break;
5524
5525                         } // switch size
5526           
5527                         ifx->generated = 1;
5528                         goto release ;
5529             
5530
5531           } else if(AOP_TYPE(right) == AOP_CRY ) {
5532             /* we know the left is not a bit, but that the right is */
5533             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5534             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5535                       pic16_popGet(AOP(right),offset));
5536             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5537
5538             /* if the two are equal, then W will be 0 and the Z bit is set
5539              * we could test Z now, or go ahead and check the high order bytes if
5540              * the variable we're comparing is larger than a byte. */
5541
5542             while(--size)
5543               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5544
5545             if ( IC_TRUE(ifx) ) {
5546               emitSKPNZ;
5547               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5548               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5549             } else {
5550               emitSKPZ;
5551               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5552               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5553             }
5554
5555           } else {
5556             /* They're both variables that are larger than bits */
5557             int s = size;
5558
5559             tlbl = newiTempLabel(NULL);
5560
5561             while(size--) {
5562               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5563               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5564
5565               if ( IC_TRUE(ifx) ) {
5566                 if(size) {
5567                   emitSKPZ;
5568                 
5569                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5570
5571                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5572                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5573                 } else {
5574                   emitSKPNZ;
5575
5576                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5577
5578
5579                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5580                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5581                 }
5582               } else {
5583                 emitSKPZ;
5584
5585                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5586
5587                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5588                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5589               }
5590               offset++;
5591             }
5592             if(s>1 && IC_TRUE(ifx)) {
5593               pic16_emitpLabel(tlbl->key);
5594               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5595             }
5596           }
5597         }
5598         /* mark the icode as generated */
5599         ifx->generated = 1;
5600         goto release ;
5601     }
5602
5603     /* if they are both bit variables */
5604     if (AOP_TYPE(left) == AOP_CRY &&
5605         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5606         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5607         if(AOP_TYPE(right) == AOP_LIT){
5608             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5609             if(lit == 0L){
5610                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5611                 pic16_emitcode("cpl","c");
5612             } else if(lit == 1L) {
5613                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5614             } else {
5615                 pic16_emitcode("clr","c");
5616             }
5617             /* AOP_TYPE(right) == AOP_CRY */
5618         } else {
5619             symbol *lbl = newiTempLabel(NULL);
5620             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5621             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5622             pic16_emitcode("cpl","c");
5623             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5624         }
5625         /* c = 1 if egal */
5626         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5627             pic16_outBitC(result);
5628             goto release ;
5629         }
5630         if (ifx) {
5631             genIfxJump (ifx,"c");
5632             goto release ;
5633         }
5634         /* if the result is used in an arithmetic operation
5635         then put the result in place */
5636         pic16_outBitC(result);
5637     } else {
5638       
5639       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5640       gencjne(left,right,result,ifx);
5641 /*
5642       if(ifx) 
5643         gencjne(left,right,newiTempLabel(NULL));
5644       else {
5645         if(IC_TRUE(ifx)->key)
5646           gencjne(left,right,IC_TRUE(ifx)->key);
5647         else
5648           gencjne(left,right,IC_FALSE(ifx)->key);
5649         ifx->generated = 1;
5650         goto release ;
5651       }
5652       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5653         pic16_aopPut(AOP(result),"a",0);
5654         goto release ;
5655       }
5656
5657       if (ifx) {
5658         genIfxJump (ifx,"a");
5659         goto release ;
5660       }
5661 */
5662       /* if the result is used in an arithmetic operation
5663          then put the result in place */
5664 /*
5665       if (AOP_TYPE(result) != AOP_CRY) 
5666         pic16_outAcc(result);
5667 */
5668       /* leave the result in acc */
5669     }
5670
5671 release:
5672     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5673     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5674     pic16_freeAsmop(result,NULL,ic,TRUE);
5675 }
5676
5677 /*-----------------------------------------------------------------*/
5678 /* ifxForOp - returns the icode containing the ifx for operand     */
5679 /*-----------------------------------------------------------------*/
5680 static iCode *ifxForOp ( operand *op, iCode *ic )
5681 {
5682     /* if true symbol then needs to be assigned */
5683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5684     if (IS_TRUE_SYMOP(op))
5685         return NULL ;
5686
5687     /* if this has register type condition and
5688     the next instruction is ifx with the same operand
5689     and live to of the operand is upto the ifx only then */
5690     if (ic->next &&
5691         ic->next->op == IFX &&
5692         IC_COND(ic->next)->key == op->key &&
5693         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5694         return ic->next;
5695
5696     if (ic->next &&
5697         ic->next->op == IFX &&
5698         IC_COND(ic->next)->key == op->key) {
5699       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5700       return ic->next;
5701     }
5702
5703     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5704     if (ic->next &&
5705         ic->next->op == IFX)
5706       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5707
5708     if (ic->next &&
5709         ic->next->op == IFX &&
5710         IC_COND(ic->next)->key == op->key) {
5711       DEBUGpic16_emitcode ("; "," key is okay");
5712       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5713                            OP_SYMBOL(op)->liveTo,
5714                            ic->next->seq);
5715     }
5716
5717
5718     return NULL;
5719 }
5720 /*-----------------------------------------------------------------*/
5721 /* genAndOp - for && operation                                     */
5722 /*-----------------------------------------------------------------*/
5723 static void genAndOp (iCode *ic)
5724 {
5725     operand *left,*right, *result;
5726 /*     symbol *tlbl; */
5727
5728     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5729     /* note here that && operations that are in an
5730     if statement are taken away by backPatchLabels
5731     only those used in arthmetic operations remain */
5732     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5733     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5734     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5735
5736     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5737
5738     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5739     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5740     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5741
5742     /* if both are bit variables */
5743 /*     if (AOP_TYPE(left) == AOP_CRY && */
5744 /*         AOP_TYPE(right) == AOP_CRY ) { */
5745 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5746 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5747 /*         pic16_outBitC(result); */
5748 /*     } else { */
5749 /*         tlbl = newiTempLabel(NULL); */
5750 /*         pic16_toBoolean(left);     */
5751 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5752 /*         pic16_toBoolean(right); */
5753 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5754 /*         pic16_outBitAcc(result); */
5755 /*     } */
5756
5757     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5758     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5759     pic16_freeAsmop(result,NULL,ic,TRUE);
5760 }
5761
5762
5763 /*-----------------------------------------------------------------*/
5764 /* genOrOp - for || operation                                      */
5765 /*-----------------------------------------------------------------*/
5766 /*
5767   tsd pic port -
5768   modified this code, but it doesn't appear to ever get called
5769 */
5770
5771 static void genOrOp (iCode *ic)
5772 {
5773     operand *left,*right, *result;
5774     symbol *tlbl;
5775
5776     /* note here that || operations that are in an
5777     if statement are taken away by backPatchLabels
5778     only those used in arthmetic operations remain */
5779     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5780     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5781     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5782     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5783
5784     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5785
5786     /* if both are bit variables */
5787     if (AOP_TYPE(left) == AOP_CRY &&
5788         AOP_TYPE(right) == AOP_CRY ) {
5789       pic16_emitcode("clrc","");
5790       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5791                AOP(left)->aopu.aop_dir,
5792                AOP(left)->aopu.aop_dir);
5793       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5794                AOP(right)->aopu.aop_dir,
5795                AOP(right)->aopu.aop_dir);
5796       pic16_emitcode("setc","");
5797
5798     } else {
5799         tlbl = newiTempLabel(NULL);
5800         pic16_toBoolean(left);
5801         emitSKPZ;
5802         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5803         pic16_toBoolean(right);
5804         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5805
5806         pic16_outBitAcc(result);
5807     }
5808
5809     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5810     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5811     pic16_freeAsmop(result,NULL,ic,TRUE);            
5812 }
5813
5814 /*-----------------------------------------------------------------*/
5815 /* isLiteralBit - test if lit == 2^n                               */
5816 /*-----------------------------------------------------------------*/
5817 static int isLiteralBit(unsigned long lit)
5818 {
5819     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5820     0x100L,0x200L,0x400L,0x800L,
5821     0x1000L,0x2000L,0x4000L,0x8000L,
5822     0x10000L,0x20000L,0x40000L,0x80000L,
5823     0x100000L,0x200000L,0x400000L,0x800000L,
5824     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5825     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5826     int idx;
5827     
5828     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5829     for(idx = 0; idx < 32; idx++)
5830         if(lit == pw[idx])
5831             return idx+1;
5832     return 0;
5833 }
5834
5835 /*-----------------------------------------------------------------*/
5836 /* continueIfTrue -                                                */
5837 /*-----------------------------------------------------------------*/
5838 static void continueIfTrue (iCode *ic)
5839 {
5840     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5841     if(IC_TRUE(ic))
5842         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5843     ic->generated = 1;
5844 }
5845
5846 /*-----------------------------------------------------------------*/
5847 /* jmpIfTrue -                                                     */
5848 /*-----------------------------------------------------------------*/
5849 static void jumpIfTrue (iCode *ic)
5850 {
5851     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5852     if(!IC_TRUE(ic))
5853         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5854     ic->generated = 1;
5855 }
5856
5857 /*-----------------------------------------------------------------*/
5858 /* jmpTrueOrFalse -                                                */
5859 /*-----------------------------------------------------------------*/
5860 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5861 {
5862     // ugly but optimized by peephole
5863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5864     if(IC_TRUE(ic)){
5865         symbol *nlbl = newiTempLabel(NULL);
5866         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5867         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5868         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5869         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5870     }
5871     else{
5872         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5873         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5874     }
5875     ic->generated = 1;
5876 }
5877
5878 /*-----------------------------------------------------------------*/
5879 /* genAnd  - code for and                                          */
5880 /*-----------------------------------------------------------------*/
5881 static void genAnd (iCode *ic, iCode *ifx)
5882 {
5883   operand *left, *right, *result;
5884   int size, offset=0;  
5885   unsigned long lit = 0L;
5886   int bytelit = 0;
5887   resolvedIfx rIfx;
5888
5889
5890   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5891   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5892   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5893   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5894
5895   resolveIfx(&rIfx,ifx);
5896
5897   /* if left is a literal & right is not then exchange them */
5898   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5899       AOP_NEEDSACC(left)) {
5900     operand *tmp = right ;
5901     right = left;
5902     left = tmp;
5903   }
5904
5905   /* if result = right then exchange them */
5906   if(pic16_sameRegs(AOP(result),AOP(right))){
5907     operand *tmp = right ;
5908     right = left;
5909     left = tmp;
5910   }
5911
5912   /* if right is bit then exchange them */
5913   if (AOP_TYPE(right) == AOP_CRY &&
5914       AOP_TYPE(left) != AOP_CRY){
5915     operand *tmp = right ;
5916     right = left;
5917     left = tmp;
5918   }
5919   if(AOP_TYPE(right) == AOP_LIT)
5920     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5921
5922   size = AOP_SIZE(result);
5923
5924   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5925
5926   // if(bit & yy)
5927   // result = bit & yy;
5928   if (AOP_TYPE(left) == AOP_CRY){
5929     // c = bit & literal;
5930     if(AOP_TYPE(right) == AOP_LIT){
5931       if(lit & 1) {
5932         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5933           // no change
5934           goto release;
5935         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5936       } else {
5937         // bit(result) = 0;
5938         if(size && (AOP_TYPE(result) == AOP_CRY)){
5939           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5940           goto release;
5941         }
5942         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5943           jumpIfTrue(ifx);
5944           goto release;
5945         }
5946         pic16_emitcode("clr","c");
5947       }
5948     } else {
5949       if (AOP_TYPE(right) == AOP_CRY){
5950         // c = bit & bit;
5951         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5953       } else {
5954         // c = bit & val;
5955         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5956         // c = lsb
5957         pic16_emitcode("rrc","a");
5958         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5959       }
5960     }
5961     // bit = c
5962     // val = c
5963     if(size)
5964       pic16_outBitC(result);
5965     // if(bit & ...)
5966     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5967       genIfxJump(ifx, "c");           
5968     goto release ;
5969   }
5970
5971   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5972   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5973   if((AOP_TYPE(right) == AOP_LIT) &&
5974      (AOP_TYPE(result) == AOP_CRY) &&
5975      (AOP_TYPE(left) != AOP_CRY)){
5976     int posbit = isLiteralBit(lit);
5977     /* left &  2^n */
5978     if(posbit){
5979       posbit--;
5980       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5981       // bit = left & 2^n
5982       if(size)
5983         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5984       // if(left &  2^n)
5985       else{
5986         if(ifx){
5987 /*
5988           if(IC_TRUE(ifx)) {
5989             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5990             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5991           } else {
5992             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5993             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5994           }
5995 */
5996           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5997                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5998           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5999           
6000           ifx->generated = 1;
6001         }
6002         goto release;
6003       }
6004     } else {
6005       symbol *tlbl = newiTempLabel(NULL);
6006       int sizel = AOP_SIZE(left);
6007       if(size)
6008         pic16_emitcode("setb","c");
6009       while(sizel--){
6010         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6011           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6012           // byte ==  2^n ?
6013           if((posbit = isLiteralBit(bytelit)) != 0)
6014             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6015           else{
6016             if(bytelit != 0x0FFL)
6017               pic16_emitcode("anl","a,%s",
6018                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6019             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6020           }
6021         }
6022         offset++;
6023       }
6024       // bit = left & literal
6025       if(size){
6026         pic16_emitcode("clr","c");
6027         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6028       }
6029       // if(left & literal)
6030       else{
6031         if(ifx)
6032           jmpTrueOrFalse(ifx, tlbl);
6033         goto release ;
6034       }
6035     }
6036     pic16_outBitC(result);
6037     goto release ;
6038   }
6039
6040   /* if left is same as result */
6041   if(pic16_sameRegs(AOP(result),AOP(left))){
6042     int know_W = -1;
6043     for(;size--; offset++,lit>>=8) {
6044       if(AOP_TYPE(right) == AOP_LIT){
6045         switch(lit & 0xff) {
6046         case 0x00:
6047           /*  and'ing with 0 has clears the result */
6048 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6049           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6050           break;
6051         case 0xff:
6052           /* and'ing with 0xff is a nop when the result and left are the same */
6053           break;
6054
6055         default:
6056           {
6057             int p = my_powof2( (~lit) & 0xff );
6058             if(p>=0) {
6059               /* only one bit is set in the literal, so use a bcf instruction */
6060 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6061               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6062
6063             } else {
6064               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6065               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6066               if(know_W != (lit&0xff))
6067                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6068               know_W = lit &0xff;
6069               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6070             }
6071           }    
6072         }
6073       } else {
6074         if (AOP_TYPE(left) == AOP_ACC) {
6075           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6076         } else {                    
6077           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6078           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6079
6080         }
6081       }
6082     }
6083
6084   } else {
6085     // left & result in different registers
6086     if(AOP_TYPE(result) == AOP_CRY){
6087       // result = bit
6088       // if(size), result in bit
6089       // if(!size && ifx), conditional oper: if(left & right)
6090       symbol *tlbl = newiTempLabel(NULL);
6091       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6092       if(size)
6093         pic16_emitcode("setb","c");
6094       while(sizer--){
6095         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6096         pic16_emitcode("anl","a,%s",
6097                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6098         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6099         offset++;
6100       }
6101       if(size){
6102         CLRC;
6103         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6104         pic16_outBitC(result);
6105       } else if(ifx)
6106         jmpTrueOrFalse(ifx, tlbl);
6107     } else {
6108       for(;(size--);offset++) {
6109         // normal case
6110         // result = left & right
6111         if(AOP_TYPE(right) == AOP_LIT){
6112           int t = (lit >> (offset*8)) & 0x0FFL;
6113           switch(t) { 
6114           case 0x00:
6115             pic16_emitcode("clrf","%s",
6116                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6117             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6118             break;
6119           case 0xff:
6120             pic16_emitcode("movf","%s,w",
6121                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6122             pic16_emitcode("movwf","%s",
6123                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6124             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6125             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6126             break;
6127           default:
6128             pic16_emitcode("movlw","0x%x",t);
6129             pic16_emitcode("andwf","%s,w",
6130                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6131             pic16_emitcode("movwf","%s",
6132                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6133               
6134             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6135             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6136             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6137           }
6138           continue;
6139         }
6140
6141         if (AOP_TYPE(left) == AOP_ACC) {
6142           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6143           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6144         } else {
6145           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6146           pic16_emitcode("andwf","%s,w",
6147                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6148           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6149           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6150         }
6151         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6152         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6153       }
6154     }
6155   }
6156
6157   release :
6158     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6159   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6160   pic16_freeAsmop(result,NULL,ic,TRUE);     
6161 }
6162
6163 /*-----------------------------------------------------------------*/
6164 /* genOr  - code for or                                            */
6165 /*-----------------------------------------------------------------*/
6166 static void genOr (iCode *ic, iCode *ifx)
6167 {
6168     operand *left, *right, *result;
6169     int size, offset=0;
6170     unsigned long lit = 0L;
6171
6172     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6173
6174     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6175     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6176     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6177
6178     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6179
6180     /* if left is a literal & right is not then exchange them */
6181     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6182         AOP_NEEDSACC(left)) {
6183         operand *tmp = right ;
6184         right = left;
6185         left = tmp;
6186     }
6187
6188     /* if result = right then exchange them */
6189     if(pic16_sameRegs(AOP(result),AOP(right))){
6190         operand *tmp = right ;
6191         right = left;
6192         left = tmp;
6193     }
6194
6195     /* if right is bit then exchange them */
6196     if (AOP_TYPE(right) == AOP_CRY &&
6197         AOP_TYPE(left) != AOP_CRY){
6198         operand *tmp = right ;
6199         right = left;
6200         left = tmp;
6201     }
6202
6203     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6204
6205     if(AOP_TYPE(right) == AOP_LIT)
6206         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6207
6208     size = AOP_SIZE(result);
6209
6210     // if(bit | yy)
6211     // xx = bit | yy;
6212     if (AOP_TYPE(left) == AOP_CRY){
6213         if(AOP_TYPE(right) == AOP_LIT){
6214             // c = bit & literal;
6215             if(lit){
6216                 // lit != 0 => result = 1
6217                 if(AOP_TYPE(result) == AOP_CRY){
6218                   if(size)
6219                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6220                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6221                   //     AOP(result)->aopu.aop_dir,
6222                   //     AOP(result)->aopu.aop_dir);
6223                     else if(ifx)
6224                         continueIfTrue(ifx);
6225                     goto release;
6226                 }
6227             } else {
6228                 // lit == 0 => result = left
6229                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6230                     goto release;
6231                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6232             }
6233         } else {
6234             if (AOP_TYPE(right) == AOP_CRY){
6235               if(pic16_sameRegs(AOP(result),AOP(left))){
6236                 // c = bit | bit;
6237                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6238                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6239                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6240
6241                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6242                          AOP(result)->aopu.aop_dir,
6243                          AOP(result)->aopu.aop_dir);
6244                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6245                          AOP(right)->aopu.aop_dir,
6246                          AOP(right)->aopu.aop_dir);
6247                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6248                          AOP(result)->aopu.aop_dir,
6249                          AOP(result)->aopu.aop_dir);
6250               } else {
6251                 if( AOP_TYPE(result) == AOP_ACC) {
6252                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6253                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6254                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6255                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6256
6257                 } else {
6258
6259                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6260                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6261                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6262                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6263
6264                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6265                                  AOP(result)->aopu.aop_dir,
6266                                  AOP(result)->aopu.aop_dir);
6267                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6268                                  AOP(right)->aopu.aop_dir,
6269                                  AOP(right)->aopu.aop_dir);
6270                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6271                                  AOP(left)->aopu.aop_dir,
6272                                  AOP(left)->aopu.aop_dir);
6273                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6274                                  AOP(result)->aopu.aop_dir,
6275                                  AOP(result)->aopu.aop_dir);
6276                 }
6277               }
6278             } else {
6279                 // c = bit | val;
6280                 symbol *tlbl = newiTempLabel(NULL);
6281                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6282
6283
6284                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6285                 if( AOP_TYPE(right) == AOP_ACC) {
6286                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6287                   emitSKPNZ;
6288                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6289                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6290                 }
6291
6292
6293
6294                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6295                     pic16_emitcode(";XXX setb","c");
6296                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6297                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6298                 pic16_toBoolean(right);
6299                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6300                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6301                     jmpTrueOrFalse(ifx, tlbl);
6302                     goto release;
6303                 } else {
6304                     CLRC;
6305                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6306                 }
6307             }
6308         }
6309         // bit = c
6310         // val = c
6311         if(size)
6312             pic16_outBitC(result);
6313         // if(bit | ...)
6314         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6315             genIfxJump(ifx, "c");           
6316         goto release ;
6317     }
6318
6319     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6320     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6321     if((AOP_TYPE(right) == AOP_LIT) &&
6322        (AOP_TYPE(result) == AOP_CRY) &&
6323        (AOP_TYPE(left) != AOP_CRY)){
6324         if(lit){
6325           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6326             // result = 1
6327             if(size)
6328                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6329             else 
6330                 continueIfTrue(ifx);
6331             goto release;
6332         } else {
6333           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6334             // lit = 0, result = boolean(left)
6335             if(size)
6336                 pic16_emitcode(";XXX setb","c");
6337             pic16_toBoolean(right);
6338             if(size){
6339                 symbol *tlbl = newiTempLabel(NULL);
6340                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6341                 CLRC;
6342                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6343             } else {
6344                 genIfxJump (ifx,"a");
6345                 goto release;
6346             }
6347         }
6348         pic16_outBitC(result);
6349         goto release ;
6350     }
6351
6352     /* if left is same as result */
6353     if(pic16_sameRegs(AOP(result),AOP(left))){
6354       int know_W = -1;
6355       for(;size--; offset++,lit>>=8) {
6356         if(AOP_TYPE(right) == AOP_LIT){
6357           if((lit & 0xff) == 0)
6358             /*  or'ing with 0 has no effect */
6359             continue;
6360           else {
6361             int p = my_powof2(lit & 0xff);
6362             if(p>=0) {
6363               /* only one bit is set in the literal, so use a bsf instruction */
6364               pic16_emitpcode(POC_BSF,
6365                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6366             } else {
6367               if(know_W != (lit & 0xff))
6368                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6369               know_W = lit & 0xff;
6370               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6371             }
6372                     
6373           }
6374         } else {
6375           if (AOP_TYPE(left) == AOP_ACC) {
6376             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6377             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6378           } else {                  
6379             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6380             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6381
6382             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6383             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6384
6385           }
6386         }
6387       }
6388     } else {
6389         // left & result in different registers
6390         if(AOP_TYPE(result) == AOP_CRY){
6391             // result = bit
6392             // if(size), result in bit
6393             // if(!size && ifx), conditional oper: if(left | right)
6394             symbol *tlbl = newiTempLabel(NULL);
6395             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6396             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6397
6398
6399             if(size)
6400                 pic16_emitcode(";XXX setb","c");
6401             while(sizer--){
6402                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6403                 pic16_emitcode(";XXX orl","a,%s",
6404                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6405                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6406                 offset++;
6407             }
6408             if(size){
6409                 CLRC;
6410                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6411                 pic16_outBitC(result);
6412             } else if(ifx)
6413                 jmpTrueOrFalse(ifx, tlbl);
6414         } else for(;(size--);offset++){
6415           // normal case
6416           // result = left & right
6417           if(AOP_TYPE(right) == AOP_LIT){
6418             int t = (lit >> (offset*8)) & 0x0FFL;
6419             switch(t) { 
6420             case 0x00:
6421               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6422               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6423
6424               pic16_emitcode("movf","%s,w",
6425                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6426               pic16_emitcode("movwf","%s",
6427                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6428               break;
6429             default:
6430               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6431               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6432               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6433
6434               pic16_emitcode("movlw","0x%x",t);
6435               pic16_emitcode("iorwf","%s,w",
6436                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6437               pic16_emitcode("movwf","%s",
6438                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6439               
6440             }
6441             continue;
6442           }
6443
6444           // faster than result <- left, anl result,right
6445           // and better if result is SFR
6446           if (AOP_TYPE(left) == AOP_ACC) {
6447             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6448             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6449           } else {
6450             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6451             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6452
6453             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6454             pic16_emitcode("iorwf","%s,w",
6455                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6456           }
6457           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6458           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6459         }
6460     }
6461
6462 release :
6463     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6464     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6465     pic16_freeAsmop(result,NULL,ic,TRUE);     
6466 }
6467
6468 /*-----------------------------------------------------------------*/
6469 /* genXor - code for xclusive or                                   */
6470 /*-----------------------------------------------------------------*/
6471 static void genXor (iCode *ic, iCode *ifx)
6472 {
6473   operand *left, *right, *result;
6474   int size, offset=0;
6475   unsigned long lit = 0L;
6476
6477   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6478
6479   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6480   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6481   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6482
6483   /* if left is a literal & right is not ||
6484      if left needs acc & right does not */
6485   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6486       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6487     operand *tmp = right ;
6488     right = left;
6489     left = tmp;
6490   }
6491
6492   /* if result = right then exchange them */
6493   if(pic16_sameRegs(AOP(result),AOP(right))){
6494     operand *tmp = right ;
6495     right = left;
6496     left = tmp;
6497   }
6498
6499   /* if right is bit then exchange them */
6500   if (AOP_TYPE(right) == AOP_CRY &&
6501       AOP_TYPE(left) != AOP_CRY){
6502     operand *tmp = right ;
6503     right = left;
6504     left = tmp;
6505   }
6506   if(AOP_TYPE(right) == AOP_LIT)
6507     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6508
6509   size = AOP_SIZE(result);
6510
6511   // if(bit ^ yy)
6512   // xx = bit ^ yy;
6513   if (AOP_TYPE(left) == AOP_CRY){
6514     if(AOP_TYPE(right) == AOP_LIT){
6515       // c = bit & literal;
6516       if(lit>>1){
6517         // lit>>1  != 0 => result = 1
6518         if(AOP_TYPE(result) == AOP_CRY){
6519           if(size)
6520             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6521             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6522           else if(ifx)
6523             continueIfTrue(ifx);
6524           goto release;
6525         }
6526         pic16_emitcode("setb","c");
6527       } else{
6528         // lit == (0 or 1)
6529         if(lit == 0){
6530           // lit == 0, result = left
6531           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6532             goto release;
6533           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6534         } else{
6535           // lit == 1, result = not(left)
6536           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6537             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6538             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6539             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6540             goto release;
6541           } else {
6542             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6543             pic16_emitcode("cpl","c");
6544           }
6545         }
6546       }
6547
6548     } else {
6549       // right != literal
6550       symbol *tlbl = newiTempLabel(NULL);
6551       if (AOP_TYPE(right) == AOP_CRY){
6552         // c = bit ^ bit;
6553         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6554       }
6555       else{
6556         int sizer = AOP_SIZE(right);
6557         // c = bit ^ val
6558         // if val>>1 != 0, result = 1
6559         pic16_emitcode("setb","c");
6560         while(sizer){
6561           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6562           if(sizer == 1)
6563             // test the msb of the lsb
6564             pic16_emitcode("anl","a,#0xfe");
6565           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6566           sizer--;
6567         }
6568         // val = (0,1)
6569         pic16_emitcode("rrc","a");
6570       }
6571       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6572       pic16_emitcode("cpl","c");
6573       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6574     }
6575     // bit = c
6576     // val = c
6577     if(size)
6578       pic16_outBitC(result);
6579     // if(bit | ...)
6580     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6581       genIfxJump(ifx, "c");           
6582     goto release ;
6583   }
6584
6585   if(pic16_sameRegs(AOP(result),AOP(left))){
6586     /* if left is same as result */
6587     for(;size--; offset++) {
6588       if(AOP_TYPE(right) == AOP_LIT){
6589         int t  = (lit >> (offset*8)) & 0x0FFL;
6590         if(t == 0x00L)
6591           continue;
6592         else
6593           if (IS_AOP_PREG(left)) {
6594             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6595             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6596             pic16_aopPut(AOP(result),"a",offset);
6597           } else {
6598             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6599             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6600             pic16_emitcode("xrl","%s,%s",
6601                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6602                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6603           }
6604       } else {
6605         if (AOP_TYPE(left) == AOP_ACC)
6606           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6607         else {
6608           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6609           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6610 /*
6611           if (IS_AOP_PREG(left)) {
6612             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6613             pic16_aopPut(AOP(result),"a",offset);
6614           } else
6615             pic16_emitcode("xrl","%s,a",
6616                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6617 */
6618         }
6619       }
6620     }
6621   } else {
6622     // left & result in different registers
6623     if(AOP_TYPE(result) == AOP_CRY){
6624       // result = bit
6625       // if(size), result in bit
6626       // if(!size && ifx), conditional oper: if(left ^ right)
6627       symbol *tlbl = newiTempLabel(NULL);
6628       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6629       if(size)
6630         pic16_emitcode("setb","c");
6631       while(sizer--){
6632         if((AOP_TYPE(right) == AOP_LIT) &&
6633            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6634           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6635         } else {
6636           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6637           pic16_emitcode("xrl","a,%s",
6638                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6639         }
6640         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6641         offset++;
6642       }
6643       if(size){
6644         CLRC;
6645         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6646         pic16_outBitC(result);
6647       } else if(ifx)
6648         jmpTrueOrFalse(ifx, tlbl);
6649     } else for(;(size--);offset++){
6650       // normal case
6651       // result = left & right
6652       if(AOP_TYPE(right) == AOP_LIT){
6653         int t = (lit >> (offset*8)) & 0x0FFL;
6654         switch(t) { 
6655         case 0x00:
6656           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6657           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6658           pic16_emitcode("movf","%s,w",
6659                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6660           pic16_emitcode("movwf","%s",
6661                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6662           break;
6663         case 0xff:
6664           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6665           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6666           pic16_emitcode("comf","%s,w",
6667                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6668           pic16_emitcode("movwf","%s",
6669                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6670           break;
6671         default:
6672           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6673           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6674           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6675           pic16_emitcode("movlw","0x%x",t);
6676           pic16_emitcode("xorwf","%s,w",
6677                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6678           pic16_emitcode("movwf","%s",
6679                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6680
6681         }
6682         continue;
6683       }
6684
6685       // faster than result <- left, anl result,right
6686       // and better if result is SFR
6687       if (AOP_TYPE(left) == AOP_ACC) {
6688         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6689         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6690       } else {
6691         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6692         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6693         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6694         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6695       }
6696       if ( AOP_TYPE(result) != AOP_ACC){
6697         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6698         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6699       }
6700     }
6701   }
6702
6703   release :
6704     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6705   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6706   pic16_freeAsmop(result,NULL,ic,TRUE);     
6707 }
6708
6709 /*-----------------------------------------------------------------*/
6710 /* genInline - write the inline code out                           */
6711 /*-----------------------------------------------------------------*/
6712 static void genInline (iCode *ic)
6713 {
6714   char *buffer, *bp, *bp1;
6715     
6716         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6717
6718         _G.inLine += (!options.asmpeep);
6719
6720         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6721         strcpy(buffer,IC_INLINE(ic));
6722
6723 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6724
6725         /* emit each line as a code */
6726         while (*bp) {
6727                 if (*bp == '\n') {
6728                         *bp++ = '\0';
6729
6730                         if(*bp1)
6731                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6732                         bp1 = bp;
6733                 } else {
6734                         if (*bp == ':') {
6735                                 bp++;
6736                                 *bp = '\0';
6737                                 bp++;
6738
6739                                 /* print label, use this special format with NULL directive
6740                                  * to denote that the argument should not be indented with tab */
6741                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6742                                 bp1 = bp;
6743                         } else
6744                                 bp++;
6745                 }
6746         }
6747
6748         if ((bp1 != bp) && *bp1)
6749                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6750
6751
6752     Safe_free(buffer);
6753
6754     _G.inLine -= (!options.asmpeep);
6755 }
6756
6757 /*-----------------------------------------------------------------*/
6758 /* genRRC - rotate right with carry                                */
6759 /*-----------------------------------------------------------------*/
6760 static void genRRC (iCode *ic)
6761 {
6762   operand *left , *result ;
6763   int size, offset = 0, same;
6764
6765   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6766
6767   /* rotate right with carry */
6768   left = IC_LEFT(ic);
6769   result=IC_RESULT(ic);
6770   pic16_aopOp (left,ic,FALSE);
6771   pic16_aopOp (result,ic,FALSE);
6772
6773   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6774
6775   same = pic16_sameRegs(AOP(result),AOP(left));
6776
6777   size = AOP_SIZE(result);    
6778
6779   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6780
6781   /* get the lsb and put it into the carry */
6782   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6783
6784   offset = 0 ;
6785
6786   while(size--) {
6787
6788     if(same) {
6789       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6790     } else {
6791       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6792       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6793     }
6794
6795     offset++;
6796   }
6797
6798   pic16_freeAsmop(left,NULL,ic,TRUE);
6799   pic16_freeAsmop(result,NULL,ic,TRUE);
6800 }
6801
6802 /*-----------------------------------------------------------------*/
6803 /* genRLC - generate code for rotate left with carry               */
6804 /*-----------------------------------------------------------------*/
6805 static void genRLC (iCode *ic)
6806 {    
6807   operand *left , *result ;
6808   int size, offset = 0;
6809   int same;
6810
6811   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6812   /* rotate right with carry */
6813   left = IC_LEFT(ic);
6814   result=IC_RESULT(ic);
6815   pic16_aopOp (left,ic,FALSE);
6816   pic16_aopOp (result,ic,FALSE);
6817
6818   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6819
6820   same = pic16_sameRegs(AOP(result),AOP(left));
6821
6822   /* move it to the result */
6823   size = AOP_SIZE(result);    
6824
6825   /* get the msb and put it into the carry */
6826   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6827
6828   offset = 0 ;
6829
6830   while(size--) {
6831
6832     if(same) {
6833       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6834     } else {
6835       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6836       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6837     }
6838
6839     offset++;
6840   }
6841
6842
6843   pic16_freeAsmop(left,NULL,ic,TRUE);
6844   pic16_freeAsmop(result,NULL,ic,TRUE);
6845 }
6846
6847
6848 /* gpasm can get the highest order bit with HIGH/UPPER
6849  * so the following probably is not needed -- VR */
6850  
6851 /*-----------------------------------------------------------------*/
6852 /* genGetHbit - generates code get highest order bit               */
6853 /*-----------------------------------------------------------------*/
6854 static void genGetHbit (iCode *ic)
6855 {
6856     operand *left, *result;
6857     left = IC_LEFT(ic);
6858     result=IC_RESULT(ic);
6859     pic16_aopOp (left,ic,FALSE);
6860     pic16_aopOp (result,ic,FALSE);
6861
6862     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6863     /* get the highest order byte into a */
6864     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6865     if(AOP_TYPE(result) == AOP_CRY){
6866         pic16_emitcode("rlc","a");
6867         pic16_outBitC(result);
6868     }
6869     else{
6870         pic16_emitcode("rl","a");
6871         pic16_emitcode("anl","a,#0x01");
6872         pic16_outAcc(result);
6873     }
6874
6875
6876     pic16_freeAsmop(left,NULL,ic,TRUE);
6877     pic16_freeAsmop(result,NULL,ic,TRUE);
6878 }
6879
6880 #if 0
6881 /*-----------------------------------------------------------------*/
6882 /* AccRol - rotate left accumulator by known count                 */
6883 /*-----------------------------------------------------------------*/
6884 static void AccRol (int shCount)
6885 {
6886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6887     shCount &= 0x0007;              // shCount : 0..7
6888     switch(shCount){
6889         case 0 :
6890             break;
6891         case 1 :
6892             pic16_emitcode("rl","a");
6893             break;
6894         case 2 :
6895             pic16_emitcode("rl","a");
6896             pic16_emitcode("rl","a");
6897             break;
6898         case 3 :
6899             pic16_emitcode("swap","a");
6900             pic16_emitcode("rr","a");
6901             break;
6902         case 4 :
6903             pic16_emitcode("swap","a");
6904             break;
6905         case 5 :
6906             pic16_emitcode("swap","a");
6907             pic16_emitcode("rl","a");
6908             break;
6909         case 6 :
6910             pic16_emitcode("rr","a");
6911             pic16_emitcode("rr","a");
6912             break;
6913         case 7 :
6914             pic16_emitcode("rr","a");
6915             break;
6916     }
6917 }
6918 #endif
6919
6920 /*-----------------------------------------------------------------*/
6921 /* AccLsh - left shift accumulator by known count                  */
6922 /*-----------------------------------------------------------------*/
6923 static void AccLsh (int shCount)
6924 {
6925         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6926         switch(shCount){
6927                 case 0 :
6928                         return;
6929                         break;
6930                 case 1 :
6931                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6932                         break;
6933                 case 2 :
6934                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6935                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6936                         break;
6937                 case 3 :
6938                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6939                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6940                         break;
6941                 case 4 :
6942                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6943                         break;
6944                 case 5 :
6945                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6946                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6947                         break;
6948                 case 6 :
6949                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6950                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6951                         break;
6952                 case 7 :
6953                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6954                         break;
6955         }
6956
6957         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6958 }
6959
6960 /*-----------------------------------------------------------------*/
6961 /* AccRsh - right shift accumulator by known count                 */
6962 /*-----------------------------------------------------------------*/
6963 static void AccRsh (int shCount, int andmask)
6964 {
6965         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6966         switch(shCount){
6967                 case 0 :
6968                         return; break;
6969                 case 1 :
6970                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6971 //                      andmask = 0;    /* no need */
6972                         break;
6973                 case 2 :
6974                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6975                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6976 //                      andmask = 0;    /* no need */
6977                         break;
6978                 case 3 :
6979                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6980                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6981                         break;
6982                 case 4 :
6983                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6984                         break;
6985                 case 5 :
6986                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6987                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6988                         break;
6989                 case 6 :
6990                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6991                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6992                         break;
6993                 case 7 :
6994                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6995                         break;
6996         }
6997         
6998         if(andmask)
6999                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7000         else
7001                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7002 }
7003
7004 #if 0
7005 /*-----------------------------------------------------------------*/
7006 /* AccSRsh - signed right shift accumulator by known count                 */
7007 /*-----------------------------------------------------------------*/
7008 static void AccSRsh (int shCount)
7009 {
7010     symbol *tlbl ;
7011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7012     if(shCount != 0){
7013         if(shCount == 1){
7014             pic16_emitcode("mov","c,acc.7");
7015             pic16_emitcode("rrc","a");
7016         } else if(shCount == 2){
7017             pic16_emitcode("mov","c,acc.7");
7018             pic16_emitcode("rrc","a");
7019             pic16_emitcode("mov","c,acc.7");
7020             pic16_emitcode("rrc","a");
7021         } else {
7022             tlbl = newiTempLabel(NULL);
7023             /* rotate right accumulator */
7024             AccRol(8 - shCount);
7025             /* and kill the higher order bits */
7026             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7027             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7028             pic16_emitcode("orl","a,#0x%02x",
7029                      (unsigned char)~SRMask[shCount]);
7030             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7031         }
7032     }
7033 }
7034 #endif
7035 /*-----------------------------------------------------------------*/
7036 /* shiftR1Left2Result - shift right one byte from left to result   */
7037 /*-----------------------------------------------------------------*/
7038 static void shiftR1Left2ResultSigned (operand *left, int offl,
7039                                 operand *result, int offr,
7040                                 int shCount)
7041 {
7042   int same;
7043
7044   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7045
7046   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7047
7048   switch(shCount) {
7049   case 1:
7050     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7051     if(same) 
7052       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7053     else {
7054       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7055       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7056     }
7057
7058     break;
7059   case 2:
7060
7061     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7062     if(same) 
7063       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7064     else {
7065       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7066       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7067     }
7068     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7069     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7070
7071     break;
7072
7073   case 3:
7074     if(same)
7075       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7076     else {
7077       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7078       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7079     }
7080
7081     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7082     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7083     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7084
7085     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7086     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7087
7088     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7089     break;
7090
7091   case 4:
7092     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7093     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7094     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7095     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7096     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7097     break;
7098   case 5:
7099     if(same) {
7100       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7101     } else {
7102       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7103       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7104     }
7105     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7106     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7107     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7108     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7109     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7110     break;
7111
7112   case 6:
7113     if(same) {
7114       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7115       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7116       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7117       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7118       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7119       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7120     } else {
7121       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7122       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7123       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7124       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7125       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7126     }
7127     break;
7128
7129   case 7:
7130     if(same) {
7131       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7132       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7133       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7134       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7135     } else {
7136       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7137       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7138       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7139     }
7140
7141   default:
7142     break;
7143   }
7144 }
7145
7146 /*-----------------------------------------------------------------*/
7147 /* shiftR1Left2Result - shift right one byte from left to result   */
7148 /*-----------------------------------------------------------------*/
7149 static void shiftR1Left2Result (operand *left, int offl,
7150                                 operand *result, int offr,
7151                                 int shCount, int sign)
7152 {
7153   int same;
7154
7155   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7156
7157   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7158
7159   /* Copy the msb into the carry if signed. */
7160   if(sign) {
7161     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7162     return;
7163   }
7164
7165
7166
7167   switch(shCount) {
7168   case 1:
7169     emitCLRC;
7170     if(same) 
7171       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7172     else {
7173       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7174       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7175     }
7176     break;
7177   case 2:
7178     emitCLRC;
7179     if(same) {
7180       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7181     } else {
7182       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7183       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7184     }
7185     emitCLRC;
7186     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7187
7188     break;
7189   case 3:
7190     if(same)
7191       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7192     else {
7193       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7194       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7195     }
7196
7197     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7198     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7199     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7200     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7201     break;
7202       
7203   case 4:
7204     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7205     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7206     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7207     break;
7208
7209   case 5:
7210     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7211     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7212     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7213     emitCLRC;
7214     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7215
7216     break;
7217   case 6:
7218
7219     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7220     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7221     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7222     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7223     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7224     break;
7225
7226   case 7:
7227
7228     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7229     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7230     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7231
7232     break;
7233
7234   default:
7235     break;
7236   }
7237 }
7238
7239 /*-----------------------------------------------------------------*/
7240 /* shiftL1Left2Result - shift left one byte from left to result    */
7241 /*-----------------------------------------------------------------*/
7242 static void shiftL1Left2Result (operand *left, int offl,
7243                                 operand *result, int offr, int shCount)
7244 {
7245   int same;
7246
7247   //    char *l;
7248   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7249
7250   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7251   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7252     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7253     //    MOVA(l);
7254     /* shift left accumulator */
7255     //AccLsh(shCount); // don't comment out just yet...
7256   //    pic16_aopPut(AOP(result),"a",offr);
7257
7258   switch(shCount) {
7259   case 1:
7260     /* Shift left 1 bit position */
7261     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7262     if(same) {
7263       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7264     } else {
7265       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7266       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7267     }
7268     break;
7269   case 2:
7270     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7271     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7272     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7273     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7274     break;
7275   case 3:
7276     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7277     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7278     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7279     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7280     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7281     break;
7282   case 4:
7283     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7284     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7285     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7286     break;
7287   case 5:
7288     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7289     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7290     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7291     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7292     break;
7293   case 6:
7294     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7295     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7296     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7297     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7298     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7299     break;
7300   case 7:
7301     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7302     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7303     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7304     break;
7305
7306   default:
7307     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7308   }
7309
7310 }
7311
7312 /*-----------------------------------------------------------------*/
7313 /* movLeft2Result - move byte from left to result                  */
7314 /*-----------------------------------------------------------------*/
7315 static void movLeft2Result (operand *left, int offl,
7316                             operand *result, int offr)
7317 {
7318   char *l;
7319   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7320   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7321     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7322
7323     if (*l == '@' && (IS_AOP_PREG(result))) {
7324       pic16_emitcode("mov","a,%s",l);
7325       pic16_aopPut(AOP(result),"a",offr);
7326     } else {
7327       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7328       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7329     }
7330   }
7331 }
7332
7333 /*-----------------------------------------------------------------*/
7334 /* shiftL2Left2Result - shift left two bytes from left to result   */
7335 /*-----------------------------------------------------------------*/
7336 static void shiftL2Left2Result (operand *left, int offl,
7337                                 operand *result, int offr, int shCount)
7338 {
7339   int same = pic16_sameRegs(AOP(result), AOP(left));
7340   int i;
7341
7342   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7343
7344   if (same && (offl != offr)) { // shift bytes
7345     if (offr > offl) {
7346        for(i=1;i>-1;i--) {
7347          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7348          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7349        }
7350     } else { // just treat as different later on
7351                 same = 0;
7352     }
7353   }
7354
7355   if(same) {
7356     switch(shCount) {
7357     case 0:
7358       break;
7359     case 1:
7360     case 2:
7361     case 3:
7362
7363       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7364       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7365       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7366
7367       while(--shCount) {
7368                 emitCLRC;
7369                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7370                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7371       }
7372
7373       break;
7374     case 4:
7375     case 5:
7376       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7377       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7378       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7379       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7380       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7381       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7382       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7383       if(shCount >=5) {
7384                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7385                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7386       }
7387       break;
7388     case 6:
7389       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7390       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7391       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7392       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7393       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7394       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7395       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7396       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7397       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7398       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7399       break;
7400     case 7:
7401       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7402       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7403       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7404       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7405       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7406     }
7407
7408   } else {
7409     switch(shCount) {
7410     case 0:
7411       break;
7412     case 1:
7413     case 2:
7414     case 3:
7415       /* note, use a mov/add for the shift since the mov has a
7416          chance of getting optimized out */
7417       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7418       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7419       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7420       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7421       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7422
7423       while(--shCount) {
7424                 emitCLRC;
7425                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7426                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7427       }
7428       break;
7429
7430     case 4:
7431     case 5:
7432       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7433       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7434       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7435       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7436       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7437       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7438       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7439       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7440
7441
7442       if(shCount == 5) {
7443                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7444                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7445       }
7446       break;
7447     case 6:
7448       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7449       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7450       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7451       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7452
7453       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7454       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7455       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7456       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7457       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7458       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7459       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7460       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7461       break;
7462     case 7:
7463       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7464       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7465       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7466       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7467       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7468     }
7469   }
7470
7471 }
7472 /*-----------------------------------------------------------------*/
7473 /* shiftR2Left2Result - shift right two bytes from left to result  */
7474 /*-----------------------------------------------------------------*/
7475 static void shiftR2Left2Result (operand *left, int offl,
7476                                 operand *result, int offr,
7477                                 int shCount, int sign)
7478 {
7479   int same = pic16_sameRegs(AOP(result), AOP(left));
7480   int i;
7481   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7482
7483   if (same && (offl != offr)) { // shift right bytes
7484     if (offr < offl) {
7485        for(i=0;i<2;i++) {
7486          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7487          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7488        }
7489     } else { // just treat as different later on
7490                 same = 0;
7491     }
7492   }
7493
7494   switch(shCount) {
7495   case 0:
7496     break;
7497   case 1:
7498   case 2:
7499   case 3:
7500     if(sign)
7501       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7502     else
7503       emitCLRC;
7504
7505     if(same) {
7506       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7507       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7508     } else {
7509       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7510       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7511       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7512       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7513     }
7514
7515     while(--shCount) {
7516       if(sign)
7517                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7518       else
7519                 emitCLRC;
7520       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7521       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7522     }
7523     break;
7524   case 4:
7525   case 5:
7526     if(same) {
7527
7528       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7529       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7530       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7531
7532       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7533       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7534       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7535       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7536     } else {
7537       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7538       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7539       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7540
7541       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7542       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7543       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7544       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7545       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7546     }
7547
7548     if(shCount >=5) {
7549       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7550       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7551     }
7552
7553     if(sign) {
7554       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7555       pic16_emitpcode(POC_BTFSC, 
7556                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7557       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7558     }
7559
7560     break;
7561
7562   case 6:
7563     if(same) {
7564
7565       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7566       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7567
7568       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7569       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7570       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7571       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7572       if(sign) {
7573         pic16_emitpcode(POC_BTFSC, 
7574                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7575         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7576       }
7577       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7578       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7579       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7580       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7581     } else {
7582       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7583       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7584       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7585       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7586       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7587       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7588       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7589       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7590       if(sign) {
7591         pic16_emitpcode(POC_BTFSC, 
7592                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7593         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7594       }
7595       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7596       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7597
7598         
7599     }
7600
7601     break;
7602   case 7:
7603     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7604     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7605     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7606     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7607     if(sign) {
7608       emitSKPNC;
7609       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7610     } else 
7611       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7612   }
7613 }
7614
7615
7616 /*-----------------------------------------------------------------*/
7617 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7618 /*-----------------------------------------------------------------*/
7619 static void shiftLLeftOrResult (operand *left, int offl,
7620                                 operand *result, int offr, int shCount)
7621 {
7622     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7623
7624     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7625     /* shift left accumulator */
7626     AccLsh(shCount);
7627     /* or with result */
7628     /* back to result */
7629     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7630 }
7631
7632 /*-----------------------------------------------------------------*/
7633 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7634 /*-----------------------------------------------------------------*/
7635 static void shiftRLeftOrResult (operand *left, int offl,
7636                                 operand *result, int offr, int shCount)
7637 {
7638     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7639     
7640     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7641     /* shift right accumulator */
7642     AccRsh(shCount, 1);
7643     /* or with result */
7644     /* back to result */
7645     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7646 }
7647
7648 /*-----------------------------------------------------------------*/
7649 /* genlshOne - left shift a one byte quantity by known count       */
7650 /*-----------------------------------------------------------------*/
7651 static void genlshOne (operand *result, operand *left, int shCount)
7652 {       
7653     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7654     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7655 }
7656
7657 /*-----------------------------------------------------------------*/
7658 /* genlshTwo - left shift two bytes by known amount != 0           */
7659 /*-----------------------------------------------------------------*/
7660 static void genlshTwo (operand *result,operand *left, int shCount)
7661 {
7662     int size;
7663     
7664     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7665     size = pic16_getDataSize(result);
7666
7667     /* if shCount >= 8 */
7668     if (shCount >= 8) {
7669         shCount -= 8 ;
7670
7671         if (size > 1){
7672             if (shCount)
7673                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7674             else 
7675                 movLeft2Result(left, LSB, result, MSB16);
7676         }
7677         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7678     }
7679
7680     /*  1 <= shCount <= 7 */
7681     else {  
7682         if(size == 1)
7683             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7684         else 
7685             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7686     }
7687 }
7688
7689 /*-----------------------------------------------------------------*/
7690 /* shiftLLong - shift left one long from left to result            */
7691 /* offr = LSB or MSB16                                             */
7692 /*-----------------------------------------------------------------*/
7693 static void shiftLLong (operand *left, operand *result, int offr )
7694 {
7695     int size = AOP_SIZE(result);
7696     int same = pic16_sameRegs(AOP(left),AOP(result));
7697         int i;
7698
7699     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7700
7701         if (same && (offr == MSB16)) { //shift one byte
7702                 for(i=size-1;i>=MSB16;i--) {
7703                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7704                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7705                 }
7706         } else {
7707                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7708         }
7709         
7710     if (size >= LSB+offr ){
7711                 if (same) {
7712                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7713                 } else {
7714                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7715                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7716                 }
7717          }
7718
7719     if(size >= MSB16+offr){
7720                 if (same) {
7721                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7722                 } else {
7723                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7724                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7725                 }
7726     }
7727
7728     if(size >= MSB24+offr){
7729                 if (same) {
7730                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7731                 } else {
7732                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7733                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7734                 }
7735     }
7736
7737     if(size > MSB32+offr){
7738                 if (same) {
7739                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7740                 } else {
7741                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7742                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7743                 }
7744     }
7745     if(offr != LSB)
7746                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7747
7748 }
7749
7750 /*-----------------------------------------------------------------*/
7751 /* genlshFour - shift four byte by a known amount != 0             */
7752 /*-----------------------------------------------------------------*/
7753 static void genlshFour (operand *result, operand *left, int shCount)
7754 {
7755     int size;
7756
7757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7758     size = AOP_SIZE(result);
7759
7760     /* if shifting more that 3 bytes */
7761     if (shCount >= 24 ) {
7762         shCount -= 24;
7763         if (shCount)
7764             /* lowest order of left goes to the highest
7765             order of the destination */
7766             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7767         else
7768             movLeft2Result(left, LSB, result, MSB32);
7769
7770                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7771                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7772                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7773
7774         return;
7775     }
7776
7777     /* more than two bytes */
7778     else if ( shCount >= 16 ) {
7779         /* lower order two bytes goes to higher order two bytes */
7780         shCount -= 16;
7781         /* if some more remaining */
7782         if (shCount)
7783             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7784         else {
7785             movLeft2Result(left, MSB16, result, MSB32);
7786             movLeft2Result(left, LSB, result, MSB24);
7787         }
7788                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7789                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7790         return;
7791     }    
7792
7793     /* if more than 1 byte */
7794     else if ( shCount >= 8 ) {
7795         /* lower order three bytes goes to higher order  three bytes */
7796         shCount -= 8;
7797         if(size == 2){
7798             if(shCount)
7799                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7800             else
7801                 movLeft2Result(left, LSB, result, MSB16);
7802         }
7803         else{   /* size = 4 */
7804             if(shCount == 0){
7805                 movLeft2Result(left, MSB24, result, MSB32);
7806                 movLeft2Result(left, MSB16, result, MSB24);
7807                 movLeft2Result(left, LSB, result, MSB16);
7808                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7809             }
7810             else if(shCount == 1)
7811                 shiftLLong(left, result, MSB16);
7812             else{
7813                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7814                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7815                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7816                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7817             }
7818         }
7819     }
7820
7821     /* 1 <= shCount <= 7 */
7822     else if(shCount <= 3)
7823     { 
7824         shiftLLong(left, result, LSB);
7825         while(--shCount >= 1)
7826             shiftLLong(result, result, LSB);
7827     }
7828     /* 3 <= shCount <= 7, optimize */
7829     else{
7830         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7831         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7832         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7833     }
7834 }
7835
7836 /*-----------------------------------------------------------------*/
7837 /* genLeftShiftLiteral - left shifting by known count              */
7838 /*-----------------------------------------------------------------*/
7839 static void genLeftShiftLiteral (operand *left,
7840                                  operand *right,
7841                                  operand *result,
7842                                  iCode *ic)
7843 {    
7844     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7845     int size;
7846
7847     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7848     pic16_freeAsmop(right,NULL,ic,TRUE);
7849
7850     pic16_aopOp(left,ic,FALSE);
7851     pic16_aopOp(result,ic,FALSE);
7852
7853     size = getSize(operandType(result));
7854
7855 #if VIEW_SIZE
7856     pic16_emitcode("; shift left ","result %d, left %d",size,
7857              AOP_SIZE(left));
7858 #endif
7859
7860     /* I suppose that the left size >= result size */
7861     if(shCount == 0){
7862         while(size--){
7863             movLeft2Result(left, size, result, size);
7864         }
7865     }
7866
7867     else if(shCount >= (size * 8))
7868         while(size--)
7869             pic16_aopPut(AOP(result),zero,size);
7870     else{
7871         switch (size) {
7872             case 1:
7873                 genlshOne (result,left,shCount);
7874                 break;
7875
7876             case 2:
7877             case 3:
7878                 genlshTwo (result,left,shCount);
7879                 break;
7880
7881             case 4:
7882                 genlshFour (result,left,shCount);
7883                 break;
7884         }
7885     }
7886     pic16_freeAsmop(left,NULL,ic,TRUE);
7887     pic16_freeAsmop(result,NULL,ic,TRUE);
7888 }
7889
7890 /*-----------------------------------------------------------------*
7891  * genMultiAsm - repeat assembly instruction for size of register.
7892  * if endian == 1, then the high byte (i.e base address + size of 
7893  * register) is used first else the low byte is used first;
7894  *-----------------------------------------------------------------*/
7895 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7896 {
7897
7898   int offset = 0;
7899
7900   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7901
7902   if(!reg)
7903     return;
7904
7905   if(!endian) {
7906     endian = 1;
7907   } else {
7908     endian = -1;
7909     offset = size-1;
7910   }
7911
7912   while(size--) {
7913     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7914     offset += endian;
7915   }
7916
7917 }
7918 /*-----------------------------------------------------------------*/
7919 /* genLeftShift - generates code for left shifting                 */
7920 /*-----------------------------------------------------------------*/
7921 static void genLeftShift (iCode *ic)
7922 {
7923   operand *left,*right, *result;
7924   int size, offset;
7925   char *l;
7926   symbol *tlbl , *tlbl1;
7927   pCodeOp *pctemp;
7928
7929   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7930
7931   right = IC_RIGHT(ic);
7932   left  = IC_LEFT(ic);
7933   result = IC_RESULT(ic);
7934
7935   pic16_aopOp(right,ic,FALSE);
7936
7937   /* if the shift count is known then do it 
7938      as efficiently as possible */
7939   if (AOP_TYPE(right) == AOP_LIT) {
7940     genLeftShiftLiteral (left,right,result,ic);
7941     return ;
7942   }
7943
7944   /* shift count is unknown then we have to form 
7945      a loop get the loop count in B : Note: we take
7946      only the lower order byte since shifting
7947      more that 32 bits make no sense anyway, ( the
7948      largest size of an object can be only 32 bits ) */  
7949
7950     
7951   pic16_aopOp(left,ic,FALSE);
7952   pic16_aopOp(result,ic,FALSE);
7953
7954   /* now move the left to the result if they are not the
7955      same */
7956   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7957       AOP_SIZE(result) > 1) {
7958
7959     size = AOP_SIZE(result);
7960     offset=0;
7961     while (size--) {
7962       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7963       if (*l == '@' && (IS_AOP_PREG(result))) {
7964
7965         pic16_emitcode("mov","a,%s",l);
7966         pic16_aopPut(AOP(result),"a",offset);
7967       } else {
7968         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7969         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7970         //pic16_aopPut(AOP(result),l,offset);
7971       }
7972       offset++;
7973     }
7974   }
7975
7976   size = AOP_SIZE(result);
7977
7978   /* if it is only one byte then */
7979   if (size == 1) {
7980     if(optimized_for_speed) {
7981       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7982       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7983       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7984       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7985       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7986       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7987       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7988       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7989       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7990       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7991       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7992       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7993     } else {
7994
7995       tlbl = newiTempLabel(NULL);
7996       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7997                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7998                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7999       }
8000
8001       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8002       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8003       pic16_emitpLabel(tlbl->key);
8004       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8005       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8006       emitSKPC;
8007       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8008     }
8009     goto release ;
8010   }
8011     
8012   if (pic16_sameRegs(AOP(left),AOP(result))) {
8013
8014     tlbl = newiTempLabel(NULL);
8015     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8016     genMultiAsm(POC_RRCF, result, size,1);
8017     pic16_emitpLabel(tlbl->key);
8018     genMultiAsm(POC_RLCF, result, size,0);
8019     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8020     emitSKPC;
8021     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8022     goto release;
8023   }
8024
8025   //tlbl = newiTempLabel(NULL);
8026   //offset = 0 ;   
8027   //tlbl1 = newiTempLabel(NULL);
8028
8029   //reAdjustPreg(AOP(result));    
8030     
8031   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8032   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8033   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8034   //MOVA(l);
8035   //pic16_emitcode("add","a,acc");         
8036   //pic16_aopPut(AOP(result),"a",offset++);
8037   //while (--size) {
8038   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8039   //  MOVA(l);
8040   //  pic16_emitcode("rlc","a");         
8041   //  pic16_aopPut(AOP(result),"a",offset++);
8042   //}
8043   //reAdjustPreg(AOP(result));
8044
8045   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8046   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8047
8048
8049   tlbl = newiTempLabel(NULL);
8050   tlbl1= newiTempLabel(NULL);
8051
8052   size = AOP_SIZE(result);
8053   offset = 1;
8054
8055   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8056
8057   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8058
8059   /* offset should be 0, 1 or 3 */
8060   
8061   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8062   emitSKPNZ;
8063   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8064
8065   pic16_emitpcode(POC_MOVWF, pctemp);
8066
8067
8068   pic16_emitpLabel(tlbl->key);
8069
8070   emitCLRC;
8071   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8072   while(--size)
8073     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8074
8075   pic16_emitpcode(POC_DECFSZ,  pctemp);
8076   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8077   pic16_emitpLabel(tlbl1->key);
8078
8079   pic16_popReleaseTempReg(pctemp);
8080
8081
8082  release:
8083   pic16_freeAsmop (right,NULL,ic,TRUE);
8084   pic16_freeAsmop(left,NULL,ic,TRUE);
8085   pic16_freeAsmop(result,NULL,ic,TRUE);
8086 }
8087
8088 /*-----------------------------------------------------------------*/
8089 /* genrshOne - right shift a one byte quantity by known count      */
8090 /*-----------------------------------------------------------------*/
8091 static void genrshOne (operand *result, operand *left,
8092                        int shCount, int sign)
8093 {
8094     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8095     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8096 }
8097
8098 /*-----------------------------------------------------------------*/
8099 /* genrshTwo - right shift two bytes by known amount != 0          */
8100 /*-----------------------------------------------------------------*/
8101 static void genrshTwo (operand *result,operand *left,
8102                        int shCount, int sign)
8103 {
8104   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8105   /* if shCount >= 8 */
8106   if (shCount >= 8) {
8107     shCount -= 8 ;
8108     if (shCount)
8109       shiftR1Left2Result(left, MSB16, result, LSB,
8110                          shCount, sign);
8111     else
8112       movLeft2Result(left, MSB16, result, LSB);
8113
8114     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8115
8116     if(sign) {
8117       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8118       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8119     }
8120   }
8121
8122   /*  1 <= shCount <= 7 */
8123   else
8124     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8125 }
8126
8127 /*-----------------------------------------------------------------*/
8128 /* shiftRLong - shift right one long from left to result           */
8129 /* offl = LSB or MSB16                                             */
8130 /*-----------------------------------------------------------------*/
8131 static void shiftRLong (operand *left, int offl,
8132                         operand *result, int sign)
8133 {
8134     int size = AOP_SIZE(result);
8135     int same = pic16_sameRegs(AOP(left),AOP(result));
8136     int i;
8137     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8138
8139         if (same && (offl == MSB16)) { //shift one byte right
8140                 for(i=MSB16;i<size;i++) {
8141                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8142                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8143                 }
8144         }
8145
8146     if(sign)
8147                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8148         else
8149                 emitCLRC;
8150
8151         if (same) {
8152                 if (offl == LSB)
8153                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8154         } else {
8155         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8156         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8157         }
8158
8159     if(offl == MSB16) {
8160         /* add sign of "a" */
8161         pic16_addSign(result, MSB32, sign);
8162         }
8163
8164         if (same) {
8165         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8166         } else {
8167         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8168         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8169         }
8170         
8171         if (same) {
8172         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8173         } else {
8174         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8175         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8176         }
8177
8178         if (same) {
8179         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8180         } else {
8181         if(offl == LSB){
8182                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8183                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8184         }
8185         }
8186 }
8187
8188 /*-----------------------------------------------------------------*/
8189 /* genrshFour - shift four byte by a known amount != 0             */
8190 /*-----------------------------------------------------------------*/
8191 static void genrshFour (operand *result, operand *left,
8192                         int shCount, int sign)
8193 {
8194   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8195   /* if shifting more that 3 bytes */
8196   if(shCount >= 24 ) {
8197     shCount -= 24;
8198     if(shCount)
8199       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8200     else
8201       movLeft2Result(left, MSB32, result, LSB);
8202
8203     pic16_addSign(result, MSB16, sign);
8204   }
8205   else if(shCount >= 16){
8206     shCount -= 16;
8207     if(shCount)
8208       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8209     else{
8210       movLeft2Result(left, MSB24, result, LSB);
8211       movLeft2Result(left, MSB32, result, MSB16);
8212     }
8213     pic16_addSign(result, MSB24, sign);
8214   }
8215   else if(shCount >= 8){
8216     shCount -= 8;
8217     if(shCount == 1)
8218       shiftRLong(left, MSB16, result, sign);
8219     else if(shCount == 0){
8220       movLeft2Result(left, MSB16, result, LSB);
8221       movLeft2Result(left, MSB24, result, MSB16);
8222       movLeft2Result(left, MSB32, result, MSB24);
8223       pic16_addSign(result, MSB32, sign);
8224     }
8225     else{ //shcount >= 2
8226       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8227       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8228       /* the last shift is signed */
8229       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8230       pic16_addSign(result, MSB32, sign);
8231     }
8232   }
8233   else{   /* 1 <= shCount <= 7 */
8234     if(shCount <= 2){
8235       shiftRLong(left, LSB, result, sign);
8236       if(shCount == 2)
8237         shiftRLong(result, LSB, result, sign);
8238     }
8239     else{
8240       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8241       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8242       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8243     }
8244   }
8245 }
8246
8247 /*-----------------------------------------------------------------*/
8248 /* genRightShiftLiteral - right shifting by known count            */
8249 /*-----------------------------------------------------------------*/
8250 static void genRightShiftLiteral (operand *left,
8251                                   operand *right,
8252                                   operand *result,
8253                                   iCode *ic,
8254                                   int sign)
8255 {    
8256   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8257   int lsize,res_size;
8258
8259   pic16_freeAsmop(right,NULL,ic,TRUE);
8260
8261   pic16_aopOp(left,ic,FALSE);
8262   pic16_aopOp(result,ic,FALSE);
8263
8264   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8265
8266 #if VIEW_SIZE
8267   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8268                  AOP_SIZE(left));
8269 #endif
8270
8271   lsize = pic16_getDataSize(left);
8272   res_size = pic16_getDataSize(result);
8273   /* test the LEFT size !!! */
8274
8275   /* I suppose that the left size >= result size */
8276   if(shCount == 0){
8277     while(res_size--)
8278       movLeft2Result(left, lsize, result, res_size);
8279   }
8280
8281   else if(shCount >= (lsize * 8)){
8282
8283     if(res_size == 1) {
8284       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8285       if(sign) {
8286         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8287         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8288       }
8289     } else {
8290
8291       if(sign) {
8292         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8293         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8294         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8295         while(res_size--)
8296           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8297
8298       } else {
8299
8300         while(res_size--)
8301           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8302       }
8303     }
8304   } else {
8305
8306     switch (res_size) {
8307     case 1:
8308       genrshOne (result,left,shCount,sign);
8309       break;
8310
8311     case 2:
8312       genrshTwo (result,left,shCount,sign);
8313       break;
8314
8315     case 4:
8316       genrshFour (result,left,shCount,sign);
8317       break;
8318     default :
8319       break;
8320     }
8321
8322   }
8323
8324   pic16_freeAsmop(left,NULL,ic,TRUE);
8325   pic16_freeAsmop(result,NULL,ic,TRUE);
8326 }
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genSignedRightShift - right shift of signed number              */
8330 /*-----------------------------------------------------------------*/
8331 static void genSignedRightShift (iCode *ic)
8332 {
8333   operand *right, *left, *result;
8334   int size, offset;
8335   //  char *l;
8336   symbol *tlbl, *tlbl1 ;
8337   pCodeOp *pctemp;
8338
8339   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8340
8341   /* we do it the hard way put the shift count in b
8342      and loop thru preserving the sign */
8343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8344
8345   right = IC_RIGHT(ic);
8346   left  = IC_LEFT(ic);
8347   result = IC_RESULT(ic);
8348
8349   pic16_aopOp(right,ic,FALSE);  
8350   pic16_aopOp(left,ic,FALSE);
8351   pic16_aopOp(result,ic,FALSE);
8352
8353
8354   if ( AOP_TYPE(right) == AOP_LIT) {
8355     genRightShiftLiteral (left,right,result,ic,1);
8356     return ;
8357   }
8358   /* shift count is unknown then we have to form 
8359      a loop get the loop count in B : Note: we take
8360      only the lower order byte since shifting
8361      more that 32 bits make no sense anyway, ( the
8362      largest size of an object can be only 32 bits ) */  
8363
8364   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8365   //pic16_emitcode("inc","b");
8366   //pic16_freeAsmop (right,NULL,ic,TRUE);
8367   //pic16_aopOp(left,ic,FALSE);
8368   //pic16_aopOp(result,ic,FALSE);
8369
8370   /* now move the left to the result if they are not the
8371      same */
8372   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8373       AOP_SIZE(result) > 1) {
8374
8375     size = AOP_SIZE(result);
8376     offset=0;
8377     while (size--) { 
8378       /*
8379         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8380         if (*l == '@' && IS_AOP_PREG(result)) {
8381
8382         pic16_emitcode("mov","a,%s",l);
8383         pic16_aopPut(AOP(result),"a",offset);
8384         } else
8385         pic16_aopPut(AOP(result),l,offset);
8386       */
8387       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8388       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8389
8390       offset++;
8391     }
8392   }
8393
8394   /* mov the highest order bit to OVR */    
8395   tlbl = newiTempLabel(NULL);
8396   tlbl1= newiTempLabel(NULL);
8397
8398   size = AOP_SIZE(result);
8399   offset = size - 1;
8400
8401   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8402
8403   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8404
8405   /* offset should be 0, 1 or 3 */
8406   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8407   emitSKPNZ;
8408   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8409
8410   pic16_emitpcode(POC_MOVWF, pctemp);
8411
8412
8413   pic16_emitpLabel(tlbl->key);
8414
8415   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8416   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8417
8418   while(--size) {
8419     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8420   }
8421
8422   pic16_emitpcode(POC_DECFSZ,  pctemp);
8423   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8424   pic16_emitpLabel(tlbl1->key);
8425
8426   pic16_popReleaseTempReg(pctemp);
8427 #if 0
8428   size = AOP_SIZE(result);
8429   offset = size - 1;
8430   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8431   pic16_emitcode("rlc","a");
8432   pic16_emitcode("mov","ov,c");
8433   /* if it is only one byte then */
8434   if (size == 1) {
8435     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8436     MOVA(l);
8437     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8438     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8439     pic16_emitcode("mov","c,ov");
8440     pic16_emitcode("rrc","a");
8441     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8442     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8443     pic16_aopPut(AOP(result),"a",0);
8444     goto release ;
8445   }
8446
8447   reAdjustPreg(AOP(result));
8448   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8449   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8450   pic16_emitcode("mov","c,ov");
8451   while (size--) {
8452     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8453     MOVA(l);
8454     pic16_emitcode("rrc","a");         
8455     pic16_aopPut(AOP(result),"a",offset--);
8456   }
8457   reAdjustPreg(AOP(result));
8458   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8459   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8460
8461  release:
8462 #endif
8463
8464   pic16_freeAsmop(left,NULL,ic,TRUE);
8465   pic16_freeAsmop(result,NULL,ic,TRUE);
8466   pic16_freeAsmop(right,NULL,ic,TRUE);
8467 }
8468
8469 /*-----------------------------------------------------------------*/
8470 /* genRightShift - generate code for right shifting                */
8471 /*-----------------------------------------------------------------*/
8472 static void genRightShift (iCode *ic)
8473 {
8474     operand *right, *left, *result;
8475     sym_link *letype ;
8476     int size, offset;
8477     char *l;
8478     symbol *tlbl, *tlbl1 ;
8479
8480     /* if signed then we do it the hard way preserve the
8481     sign bit moving it inwards */
8482     letype = getSpec(operandType(IC_LEFT(ic)));
8483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8484
8485     if (!SPEC_USIGN(letype)) {
8486         genSignedRightShift (ic);
8487         return ;
8488     }
8489
8490     /* signed & unsigned types are treated the same : i.e. the
8491     signed is NOT propagated inwards : quoting from the
8492     ANSI - standard : "for E1 >> E2, is equivalent to division
8493     by 2**E2 if unsigned or if it has a non-negative value,
8494     otherwise the result is implementation defined ", MY definition
8495     is that the sign does not get propagated */
8496
8497     right = IC_RIGHT(ic);
8498     left  = IC_LEFT(ic);
8499     result = IC_RESULT(ic);
8500
8501     pic16_aopOp(right,ic,FALSE);
8502
8503     /* if the shift count is known then do it 
8504     as efficiently as possible */
8505     if (AOP_TYPE(right) == AOP_LIT) {
8506         genRightShiftLiteral (left,right,result,ic, 0);
8507         return ;
8508     }
8509
8510     /* shift count is unknown then we have to form 
8511     a loop get the loop count in B : Note: we take
8512     only the lower order byte since shifting
8513     more that 32 bits make no sense anyway, ( the
8514     largest size of an object can be only 32 bits ) */  
8515
8516     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8517     pic16_emitcode("inc","b");
8518     pic16_aopOp(left,ic,FALSE);
8519     pic16_aopOp(result,ic,FALSE);
8520
8521     /* now move the left to the result if they are not the
8522     same */
8523     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8524         AOP_SIZE(result) > 1) {
8525
8526         size = AOP_SIZE(result);
8527         offset=0;
8528         while (size--) {
8529             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8530             if (*l == '@' && IS_AOP_PREG(result)) {
8531
8532                 pic16_emitcode("mov","a,%s",l);
8533                 pic16_aopPut(AOP(result),"a",offset);
8534             } else
8535                 pic16_aopPut(AOP(result),l,offset);
8536             offset++;
8537         }
8538     }
8539
8540     tlbl = newiTempLabel(NULL);
8541     tlbl1= newiTempLabel(NULL);
8542     size = AOP_SIZE(result);
8543     offset = size - 1;
8544
8545     /* if it is only one byte then */
8546     if (size == 1) {
8547
8548       tlbl = newiTempLabel(NULL);
8549       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8550         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8551         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8552       }
8553
8554       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8555       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8556       pic16_emitpLabel(tlbl->key);
8557       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8558       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8559       emitSKPC;
8560       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8561
8562       goto release ;
8563     }
8564
8565     reAdjustPreg(AOP(result));
8566     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8567     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8568     CLRC;
8569     while (size--) {
8570         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8571         MOVA(l);
8572         pic16_emitcode("rrc","a");         
8573         pic16_aopPut(AOP(result),"a",offset--);
8574     }
8575     reAdjustPreg(AOP(result));
8576
8577     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8578     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8579
8580 release:
8581     pic16_freeAsmop(left,NULL,ic,TRUE);
8582     pic16_freeAsmop (right,NULL,ic,TRUE);
8583     pic16_freeAsmop(result,NULL,ic,TRUE);
8584 }
8585
8586 /*-----------------------------------------------------------------*/
8587 /* genUnpackBits - generates code for unpacking bits               */
8588 /*-----------------------------------------------------------------*/
8589 static void genUnpackBits (operand *result, char *rname, int ptype)
8590 {    
8591     int shCnt ;
8592     int rlen = 0 ;
8593     sym_link *etype;
8594     int offset = 0 ;
8595
8596         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8597         etype = getSpec(operandType(result));
8598
8599         /* read the first byte  */
8600         switch (ptype) {
8601                 case POINTER:
8602                 case IPOINTER:
8603                 case PPOINTER:
8604                 case FPOINTER:
8605                 case GPOINTER:
8606                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8607                         break;
8608                 case CPOINTER:
8609                         pic16_emitcode("clr","a");
8610                         pic16_emitcode("movc","a","@a+dptr");
8611                         break;
8612         }
8613         
8614
8615         /* if we have bitdisplacement then it fits   */
8616         /* into this byte completely or if length is */
8617         /* less than a byte                          */
8618         if ((shCnt = SPEC_BSTR(etype)) || 
8619                 (SPEC_BLEN(etype) <= 8))  {
8620
8621                 /* shift right acc */
8622                 AccRsh(shCnt, 0);
8623
8624                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8625                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8626
8627 /* VR -- normally I would use the following, but since we use the hack,
8628  * to avoid the masking from AccRsh, why not mask it right now? */
8629
8630 /*
8631                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8632 */
8633
8634                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8635           return ;
8636         }
8637
8638
8639
8640         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8641         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8642         exit(-1);
8643
8644     /* bit field did not fit in a byte  */
8645     rlen = SPEC_BLEN(etype) - 8;
8646     pic16_aopPut(AOP(result),"a",offset++);
8647
8648     while (1)  {
8649
8650         switch (ptype) {
8651         case POINTER:
8652         case IPOINTER:
8653             pic16_emitcode("inc","%s",rname);
8654             pic16_emitcode("mov","a,@%s",rname);
8655             break;
8656             
8657         case PPOINTER:
8658             pic16_emitcode("inc","%s",rname);
8659             pic16_emitcode("movx","a,@%s",rname);
8660             break;
8661
8662         case FPOINTER:
8663             pic16_emitcode("inc","dptr");
8664             pic16_emitcode("movx","a,@dptr");
8665             break;
8666             
8667         case CPOINTER:
8668             pic16_emitcode("clr","a");
8669             pic16_emitcode("inc","dptr");
8670             pic16_emitcode("movc","a","@a+dptr");
8671             break;
8672             
8673         case GPOINTER:
8674             pic16_emitcode("inc","dptr");
8675             pic16_emitcode("lcall","__gptrget");
8676             break;
8677         }
8678
8679         rlen -= 8;            
8680         /* if we are done */
8681         if ( rlen <= 0 )
8682             break ;
8683         
8684         pic16_aopPut(AOP(result),"a",offset++);
8685                               
8686     }
8687     
8688     if (rlen) {
8689         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8690         pic16_aopPut(AOP(result),"a",offset);          
8691     }
8692     
8693     return ;
8694 }
8695
8696
8697 static void genDataPointerGet(operand *left,
8698                               operand *result,
8699                               iCode *ic)
8700 {
8701   int size, offset = 0, leoffset=0 ;
8702
8703         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8704         pic16_aopOp(result, ic, FALSE);
8705
8706         size = AOP_SIZE(result);
8707 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8708
8709
8710 #if 0
8711         /* The following tests may save a redudant movff instruction when
8712          * accessing unions */
8713          
8714         /* if they are the same */
8715         if (operandsEqu (left, result)) {
8716                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8717                 goto release;
8718         }
8719
8720         /* if they are the same registers */
8721         if (pic16_sameRegs(AOP(left),AOP(result))) {
8722                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8723                 goto release;
8724         }
8725 #endif
8726
8727 #if 0
8728         if ( AOP_TYPE(left) == AOP_PCODE) {
8729                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
8730                                 AOP(left)->aopu.pcop->name,
8731                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
8732                                 PCOR(AOP(left)->aopu.pcop)->instance:
8733                                 PCOI(AOP(left)->aopu.pcop)->offset);
8734         }
8735 #endif
8736
8737         if(AOP(left)->aopu.pcop->type == PO_DIR)
8738                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8739
8740         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8741
8742         while (size--) {
8743                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8744                 
8745                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8746                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8747                         mov2w(AOP(left), offset); // patch 8
8748                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8749                 } else {
8750                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8751                                 pic16_popGet(AOP(left), offset), //patch 8
8752                                 pic16_popGet(AOP(result), offset)));
8753                 }
8754
8755                 offset++;
8756                 leoffset++;
8757         }
8758
8759 //release:
8760     pic16_freeAsmop(result,NULL,ic,TRUE);
8761 }
8762
8763 void pic16_loadFSR0(operand *op)
8764 {
8765         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8766 }
8767
8768
8769 /*-----------------------------------------------------------------*/
8770 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8771 /*-----------------------------------------------------------------*/
8772 static void genNearPointerGet (operand *left, 
8773                                operand *result, 
8774                                iCode *ic)
8775 {
8776     asmop *aop = NULL;
8777     //regs *preg = NULL ;
8778     sym_link *rtype, *retype;
8779     sym_link *ltype = operandType(left);    
8780
8781         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8782         rtype = operandType(result);
8783         retype= getSpec(rtype);
8784     
8785         pic16_aopOp(left,ic,FALSE);
8786
8787         pic16_DumpOp("(left)",left);
8788         pic16_DumpOp("(result)",result);
8789
8790         /* if left is rematerialisable and
8791          * result is not bit variable type and
8792          * the left is pointer to data space i.e
8793          * lower 128 bytes of space */
8794         if (AOP_TYPE(left) == AOP_PCODE
8795                 && !IS_BITFIELD(retype)
8796                 && DCL_TYPE(ltype) == POINTER) {
8797
8798                 genDataPointerGet (left,result,ic);
8799                 pic16_freeAsmop(left, NULL, ic, TRUE);
8800           return ;
8801         }
8802     
8803         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8804
8805         /* if the value is already in a pointer register
8806          * then don't need anything more */
8807         if (!AOP_INPREG(AOP(left))) {
8808                 /* otherwise get a free pointer register */
8809                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8810                 
8811                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8812                 if( (AOP_TYPE(left) == AOP_PCODE) 
8813                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8814                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
8815                 {
8816                         pic16_loadFSR0( left );  // patch 10
8817                 } else {
8818                         // set up FSR0 with address from left
8819                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
8820                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
8821                 }
8822         }
8823 //       else
8824 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8825     
8826         pic16_aopOp (result,ic,FALSE);
8827     
8828       /* if bitfield then unpack the bits */
8829     if (IS_BITFIELD(retype)) 
8830         genUnpackBits (result, NULL, POINTER);
8831     else {
8832         /* we have can just get the values */
8833       int size = AOP_SIZE(result);
8834       int offset = 0;   
8835         
8836       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8837
8838
8839         /* fsr0 is loaded already -- VR */
8840 //      pic16_loadFSR0( left );
8841
8842 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8843 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8844       while(size--) {
8845
8846         if(size) {
8847                 pic16_emitpcode(POC_MOVFF,
8848                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8849                                 pic16_popGet(AOP(result), offset++)));
8850         } else {
8851                 pic16_emitpcode(POC_MOVFF,
8852                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8853                                 pic16_popGet(AOP(result), offset++)));
8854         }
8855       }
8856 #if 0
8857 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8858 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8859         if(size)
8860           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8861 #endif
8862 /*
8863         while (size--) {
8864             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8865
8866                 pic16_emitcode("mov","a,@%s",rname);
8867                 pic16_aopPut(AOP(result),"a",offset);
8868             } else {
8869                 sprintf(buffer,"@%s",rname);
8870                 pic16_aopPut(AOP(result),buffer,offset);
8871             }
8872             offset++ ;
8873             if (size)
8874                 pic16_emitcode("inc","%s",rname);
8875         }
8876 */
8877     }
8878
8879     /* now some housekeeping stuff */
8880     if (aop) {
8881         /* we had to allocate for this iCode */
8882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8883         pic16_freeAsmop(NULL,aop,ic,TRUE);
8884     } else { 
8885         /* we did not allocate which means left
8886            already in a pointer register, then
8887            if size > 0 && this could be used again
8888            we have to point it back to where it 
8889            belongs */
8890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8891         if (AOP_SIZE(result) > 1 &&
8892             !OP_SYMBOL(left)->remat &&
8893             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8894               ic->depth )) {
8895 //          int size = AOP_SIZE(result) - 1;
8896 //          while (size--)
8897 //              pic16_emitcode("dec","%s",rname);
8898         }
8899     }
8900
8901     /* done */
8902     pic16_freeAsmop(left,NULL,ic,TRUE);
8903     pic16_freeAsmop(result,NULL,ic,TRUE);
8904      
8905 }
8906
8907 /*-----------------------------------------------------------------*/
8908 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8909 /*-----------------------------------------------------------------*/
8910 static void genPagedPointerGet (operand *left, 
8911                                operand *result, 
8912                                iCode *ic)
8913 {
8914     asmop *aop = NULL;
8915     regs *preg = NULL ;
8916     char *rname ;
8917     sym_link *rtype, *retype;    
8918
8919     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8920
8921     rtype = operandType(result);
8922     retype= getSpec(rtype);
8923     
8924     pic16_aopOp(left,ic,FALSE);
8925
8926   /* if the value is already in a pointer register
8927        then don't need anything more */
8928     if (!AOP_INPREG(AOP(left))) {
8929         /* otherwise get a free pointer register */
8930         aop = newAsmop(0);
8931         preg = getFreePtr(ic,&aop,FALSE);
8932         pic16_emitcode("mov","%s,%s",
8933                 preg->name,
8934                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8935         rname = preg->name ;
8936     } else
8937         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8938     
8939     pic16_freeAsmop(left,NULL,ic,TRUE);
8940     pic16_aopOp (result,ic,FALSE);
8941
8942     /* if bitfield then unpack the bits */
8943     if (IS_BITFIELD(retype)) 
8944         genUnpackBits (result,rname,PPOINTER);
8945     else {
8946         /* we have can just get the values */
8947         int size = AOP_SIZE(result);
8948         int offset = 0 ;        
8949         
8950         while (size--) {
8951             
8952             pic16_emitcode("movx","a,@%s",rname);
8953             pic16_aopPut(AOP(result),"a",offset);
8954             
8955             offset++ ;
8956             
8957             if (size)
8958                 pic16_emitcode("inc","%s",rname);
8959         }
8960     }
8961
8962     /* now some housekeeping stuff */
8963     if (aop) {
8964         /* we had to allocate for this iCode */
8965         pic16_freeAsmop(NULL,aop,ic,TRUE);
8966     } else { 
8967         /* we did not allocate which means left
8968            already in a pointer register, then
8969            if size > 0 && this could be used again
8970            we have to point it back to where it 
8971            belongs */
8972         if (AOP_SIZE(result) > 1 &&
8973             !OP_SYMBOL(left)->remat &&
8974             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8975               ic->depth )) {
8976             int size = AOP_SIZE(result) - 1;
8977             while (size--)
8978                 pic16_emitcode("dec","%s",rname);
8979         }
8980     }
8981
8982     /* done */
8983     pic16_freeAsmop(result,NULL,ic,TRUE);
8984     
8985         
8986 }
8987
8988 /*-----------------------------------------------------------------*/
8989 /* genFarPointerGet - gget value from far space                    */
8990 /*-----------------------------------------------------------------*/
8991 static void genFarPointerGet (operand *left,
8992                               operand *result, iCode *ic)
8993 {
8994     int size, offset ;
8995     sym_link *retype = getSpec(operandType(result));
8996
8997     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8998
8999     pic16_aopOp(left,ic,FALSE);
9000
9001     /* if the operand is already in dptr 
9002     then we do nothing else we move the value to dptr */
9003     if (AOP_TYPE(left) != AOP_STR) {
9004         /* if this is remateriazable */
9005         if (AOP_TYPE(left) == AOP_IMMD)
9006             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9007         else { /* we need to get it byte by byte */
9008             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9009             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9010             if (options.model == MODEL_FLAT24)
9011             {
9012                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9013             }
9014         }
9015     }
9016     /* so dptr know contains the address */
9017     pic16_freeAsmop(left,NULL,ic,TRUE);
9018     pic16_aopOp(result,ic,FALSE);
9019
9020     /* if bit then unpack */
9021     if (IS_BITFIELD(retype)) 
9022         genUnpackBits(result,"dptr",FPOINTER);
9023     else {
9024         size = AOP_SIZE(result);
9025         offset = 0 ;
9026
9027         while (size--) {
9028             pic16_emitcode("movx","a,@dptr");
9029             pic16_aopPut(AOP(result),"a",offset++);
9030             if (size)
9031                 pic16_emitcode("inc","dptr");
9032         }
9033     }
9034
9035     pic16_freeAsmop(result,NULL,ic,TRUE);
9036 }
9037 #if 0
9038 /*-----------------------------------------------------------------*/
9039 /* genCodePointerGet - get value from code space                  */
9040 /*-----------------------------------------------------------------*/
9041 static void genCodePointerGet (operand *left,
9042                                 operand *result, iCode *ic)
9043 {
9044     int size, offset ;
9045     sym_link *retype = getSpec(operandType(result));
9046
9047     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9048
9049     pic16_aopOp(left,ic,FALSE);
9050
9051     /* if the operand is already in dptr 
9052     then we do nothing else we move the value to dptr */
9053     if (AOP_TYPE(left) != AOP_STR) {
9054         /* if this is remateriazable */
9055         if (AOP_TYPE(left) == AOP_IMMD)
9056             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9057         else { /* we need to get it byte by byte */
9058             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9059             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9060             if (options.model == MODEL_FLAT24)
9061             {
9062                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9063             }
9064         }
9065     }
9066     /* so dptr know contains the address */
9067     pic16_freeAsmop(left,NULL,ic,TRUE);
9068     pic16_aopOp(result,ic,FALSE);
9069
9070     /* if bit then unpack */
9071     if (IS_BITFIELD(retype)) 
9072         genUnpackBits(result,"dptr",CPOINTER);
9073     else {
9074         size = AOP_SIZE(result);
9075         offset = 0 ;
9076
9077         while (size--) {
9078             pic16_emitcode("clr","a");
9079             pic16_emitcode("movc","a,@a+dptr");
9080             pic16_aopPut(AOP(result),"a",offset++);
9081             if (size)
9082                 pic16_emitcode("inc","dptr");
9083         }
9084     }
9085
9086     pic16_freeAsmop(result,NULL,ic,TRUE);
9087 }
9088 #endif
9089 /*-----------------------------------------------------------------*/
9090 /* genGenPointerGet - gget value from generic pointer space        */
9091 /*-----------------------------------------------------------------*/
9092 static void genGenPointerGet (operand *left,
9093                               operand *result, iCode *ic)
9094 {
9095   int size, offset, lit;
9096   sym_link *retype = getSpec(operandType(result));
9097
9098         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9099         pic16_aopOp(left,ic,FALSE);
9100         pic16_aopOp(result,ic,FALSE);
9101         size = AOP_SIZE(result);
9102
9103         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9104
9105         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9106
9107                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9108                 // load FSR0 from immediate
9109                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9110
9111 //              pic16_loadFSR0( left );
9112
9113                 offset = 0;
9114                 while(size--) {
9115                         if(size) {
9116                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9117                         } else {
9118                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9119                         }
9120                         offset++;
9121                 }
9122                 goto release;
9123
9124         }
9125         else { /* we need to get it byte by byte */
9126                 // set up FSR0 with address from left
9127                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9128                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9129
9130                 offset = 0 ;
9131
9132                 while(size--) {
9133                         if(size) {
9134                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9135                         } else {
9136                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9137                         }
9138                         offset++;
9139                 }
9140                 goto release;
9141         }
9142
9143   /* if bit then unpack */
9144         if (IS_BITFIELD(retype)) 
9145                 genUnpackBits(result,"BAD",GPOINTER);
9146
9147         release:
9148         pic16_freeAsmop(left,NULL,ic,TRUE);
9149         pic16_freeAsmop(result,NULL,ic,TRUE);
9150
9151 }
9152
9153 /*-----------------------------------------------------------------*/
9154 /* genConstPointerGet - get value from const generic pointer space */
9155 /*-----------------------------------------------------------------*/
9156 static void genConstPointerGet (operand *left,
9157                                 operand *result, iCode *ic)
9158 {
9159   //sym_link *retype = getSpec(operandType(result));
9160   // symbol *albl = newiTempLabel(NULL);        // patch 15
9161   // symbol *blbl = newiTempLabel(NULL);        //
9162   // PIC_OPCODE poc;                            // patch 15
9163   int size;
9164   int offset = 0;
9165
9166   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9167   pic16_aopOp(left,ic,FALSE);
9168   pic16_aopOp(result,ic,TRUE);
9169   size = AOP_SIZE(result);
9170
9171   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9172
9173   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9174 #if 0                                                                   // patch 15
9175   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9176   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9177   pic16_emitpLabel(albl->key);
9178
9179   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9180     
9181   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9182   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9183   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9184   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9185   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9186
9187   pic16_emitpLabel(blbl->key);
9188
9189   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9190 #endif                                                                  // patch 15
9191
9192
9193   // set up table pointer
9194   if( (AOP_TYPE(left) == AOP_PCODE) 
9195       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9196           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9197     {
9198       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9199       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9200       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9201       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9202       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9203       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9204     }
9205   else
9206     {
9207       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9208       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9209       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9210     }
9211
9212
9213   while(size--)
9214     {
9215       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9216       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9217       offset++;
9218     }
9219                                                                         // .... patch 15
9220   pic16_freeAsmop(left,NULL,ic,TRUE);
9221   pic16_freeAsmop(result,NULL,ic,TRUE);
9222
9223 }
9224 /*-----------------------------------------------------------------*/
9225 /* genPointerGet - generate code for pointer get                   */
9226 /*-----------------------------------------------------------------*/
9227 static void genPointerGet (iCode *ic)
9228 {
9229     operand *left, *result ;
9230     sym_link *type, *etype;
9231     int p_type;
9232
9233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9234
9235     left = IC_LEFT(ic);
9236     result = IC_RESULT(ic) ;
9237
9238     /* depending on the type of pointer we need to
9239     move it to the correct pointer register */
9240     type = operandType(left);
9241     etype = getSpec(type);
9242
9243 #if 0
9244     if (IS_PTR_CONST(type))
9245 #else
9246     if (IS_CODEPTR(type))
9247 #endif
9248       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9249
9250     /* if left is of type of pointer then it is simple */
9251     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9252         p_type = DCL_TYPE(type);
9253     else {
9254         /* we have to go by the storage class */
9255         p_type = PTR_TYPE(SPEC_OCLS(etype));
9256
9257         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9258
9259         if (SPEC_OCLS(etype)->codesp ) {
9260           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9261           //p_type = CPOINTER ; 
9262         }
9263         else
9264             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9265               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9266                /*p_type = FPOINTER ;*/ 
9267             else
9268                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9269                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9270 /*                  p_type = PPOINTER; */
9271                 else
9272                     if (SPEC_OCLS(etype) == idata )
9273                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9274 /*                      p_type = IPOINTER; */
9275                     else
9276                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9277 /*                      p_type = POINTER ; */
9278     }
9279
9280     /* now that we have the pointer type we assign
9281     the pointer values */
9282     switch (p_type) {
9283
9284     case POINTER:       
9285     case IPOINTER:
9286         genNearPointerGet (left,result,ic);
9287         break;
9288
9289     case PPOINTER:
9290         genPagedPointerGet(left,result,ic);
9291         break;
9292
9293     case FPOINTER:
9294         genFarPointerGet (left,result,ic);
9295         break;
9296
9297     case CPOINTER:
9298         genConstPointerGet (left,result,ic);
9299         //pic16_emitcodePointerGet (left,result,ic);
9300         break;
9301
9302     case GPOINTER:
9303 #if 0
9304       if (IS_PTR_CONST(type))
9305         genConstPointerGet (left,result,ic);
9306       else
9307 #endif
9308         genGenPointerGet (left,result,ic);
9309       break;
9310     }
9311
9312 }
9313
9314 /*-----------------------------------------------------------------*/
9315 /* genPackBits - generates code for packed bit storage             */
9316 /*-----------------------------------------------------------------*/
9317 static void genPackBits (sym_link    *etype ,
9318                          operand *right ,
9319                          char *rname, int p_type)
9320 {
9321   int shCnt = 0 ;
9322   int offset = 0  ;
9323   int rLen = 0 ;
9324   int blen, bstr ;   
9325   char *l ;
9326
9327         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9328         blen = SPEC_BLEN(etype);
9329         bstr = SPEC_BSTR(etype);
9330
9331         if(AOP_TYPE(right) == AOP_LIT) {
9332                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9333                 offset++;
9334         } else
9335                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9336
9337 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9338         MOVA(l);   
9339 */
9340         /* if the bit lenth is less than or    */
9341         /* it exactly fits a byte then         */
9342         if((shCnt=SPEC_BSTR(etype))
9343                 || SPEC_BLEN(etype) <= 8 )  {
9344
9345                 /* shift left acc */
9346                 AccLsh(shCnt);
9347
9348                 /* using PRODL as a temporary register here */
9349                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9350
9351                 switch (p_type) {
9352                         case FPOINTER:
9353                         case POINTER:
9354                         case GPOINTER:
9355                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9356 //                              pic16_emitcode ("mov","b,a");
9357 //                              pic16_emitcode("mov","a,@%s",rname);
9358                                 break;
9359                 }
9360 #if 1
9361                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9362                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9363                                         (unsigned char)(0xff >> (8-bstr))) ));
9364                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9365                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9366 #endif
9367
9368 #if 0
9369                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9370                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9371                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9372                 pic16_emitcode ("orl","a,b");
9373                 if (p_type == GPOINTER)
9374                         pic16_emitcode("pop","b");
9375
9376                 
9377                 switch (p_type) {
9378                         case POINTER:
9379                                 pic16_emitcode("mov","@%s,a",rname);
9380                                 break;
9381                         case FPOINTER:
9382                                 pic16_emitcode("movx","@dptr,a");
9383                                 break;
9384                         case GPOINTER:
9385                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9386                                 break;
9387                 }
9388 #endif
9389
9390           return;
9391         }
9392
9393
9394         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9395         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9396         exit(-1);
9397
9398
9399     /* if we r done */
9400     if ( SPEC_BLEN(etype) <= 8 )
9401         return ;
9402
9403     pic16_emitcode("inc","%s",rname);
9404     rLen = SPEC_BLEN(etype) ;     
9405
9406
9407
9408     /* now generate for lengths greater than one byte */
9409     while (1) {
9410
9411         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9412
9413         rLen -= 8 ;
9414         if (rLen <= 0 )
9415             break ;
9416
9417         switch (p_type) {
9418             case POINTER:
9419                 if (*l == '@') {
9420                     MOVA(l);
9421                     pic16_emitcode("mov","@%s,a",rname);
9422                 } else
9423                     pic16_emitcode("mov","@%s,%s",rname,l);
9424                 break;
9425
9426             case FPOINTER:
9427                 MOVA(l);
9428                 pic16_emitcode("movx","@dptr,a");
9429                 break;
9430
9431             case GPOINTER:
9432                 MOVA(l);
9433                 DEBUGpic16_emitcode(";lcall","__gptrput");
9434                 break;  
9435         }   
9436         pic16_emitcode ("inc","%s",rname);
9437     }
9438
9439     MOVA(l);
9440
9441     /* last last was not complete */
9442     if (rLen)   {
9443         /* save the byte & read byte */
9444         switch (p_type) {
9445             case POINTER:
9446                 pic16_emitcode ("mov","b,a");
9447                 pic16_emitcode("mov","a,@%s",rname);
9448                 break;
9449
9450             case FPOINTER:
9451                 pic16_emitcode ("mov","b,a");
9452                 pic16_emitcode("movx","a,@dptr");
9453                 break;
9454
9455             case GPOINTER:
9456                 pic16_emitcode ("push","b");
9457                 pic16_emitcode ("push","acc");
9458                 pic16_emitcode ("lcall","__gptrget");
9459                 pic16_emitcode ("pop","b");
9460                 break;
9461         }
9462
9463         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9464         pic16_emitcode ("orl","a,b");
9465     }
9466
9467     if (p_type == GPOINTER)
9468         pic16_emitcode("pop","b");
9469
9470     switch (p_type) {
9471
9472     case POINTER:
9473         pic16_emitcode("mov","@%s,a",rname);
9474         break;
9475         
9476     case FPOINTER:
9477         pic16_emitcode("movx","@dptr,a");
9478         break;
9479         
9480     case GPOINTER:
9481         DEBUGpic16_emitcode(";lcall","__gptrput");
9482         break;                  
9483     }
9484 }
9485 /*-----------------------------------------------------------------*/
9486 /* genDataPointerSet - remat pointer to data space                 */
9487 /*-----------------------------------------------------------------*/
9488 static void genDataPointerSet(operand *right,
9489                               operand *result,
9490                               iCode *ic)
9491 {
9492     int size, offset = 0, resoffset=0 ;
9493
9494     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9495     pic16_aopOp(right,ic,FALSE);
9496
9497     size = AOP_SIZE(right);
9498
9499 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9500
9501 #if 0
9502     if ( AOP_TYPE(result) == AOP_PCODE) {
9503       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9504               AOP(result)->aopu.pcop->name,
9505                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9506               PCOR(AOP(result)->aopu.pcop)->instance:
9507               PCOI(AOP(result)->aopu.pcop)->offset);
9508     }
9509 #endif
9510
9511         if(AOP(result)->aopu.pcop->type == PO_DIR)
9512                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9513
9514         while (size--) {
9515                 if (AOP_TYPE(right) == AOP_LIT) {
9516                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9517
9518                         lit = lit >> (8*offset);
9519                         if(lit&0xff) {
9520                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9521                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9522                         } else {
9523                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9524                         }
9525                 } else {
9526                         mov2w(AOP(right), offset);
9527                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9528                 }
9529                 offset++;
9530                 resoffset++;
9531         }
9532
9533     pic16_freeAsmop(right,NULL,ic,TRUE);
9534 }
9535
9536
9537
9538 /*-----------------------------------------------------------------*/
9539 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9540 /*-----------------------------------------------------------------*/
9541 static void genNearPointerSet (operand *right,
9542                                operand *result, 
9543                                iCode *ic)
9544 {
9545   asmop *aop = NULL;
9546   char *l;
9547   sym_link *retype;
9548   sym_link *ptype = operandType(result);
9549   sym_link *resetype;
9550     
9551         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9552         retype= getSpec(operandType(right));
9553         resetype = getSpec(operandType(result));
9554   
9555         pic16_aopOp(result,ic,FALSE);
9556     
9557         /* if the result is rematerializable &
9558          * in data space & not a bit variable */
9559         
9560         /* and result is not a bit variable */
9561         if (AOP_TYPE(result) == AOP_PCODE
9562 //              && AOP_TYPE(result) == AOP_IMMD
9563                 && DCL_TYPE(ptype) == POINTER
9564                 && !IS_BITFIELD(retype)
9565                 && !IS_BITFIELD(resetype)) {
9566
9567                 genDataPointerSet (right,result,ic);
9568                 pic16_freeAsmop(result,NULL,ic,TRUE);
9569           return;
9570         }
9571
9572         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9573         pic16_aopOp(right,ic,FALSE);
9574         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9575
9576         /* if the value is already in a pointer register
9577          * then don't need anything more */
9578         if (!AOP_INPREG(AOP(result))) {
9579                 /* otherwise get a free pointer register */
9580                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9581
9582                 if( (AOP_TYPE(result) == AOP_PCODE) 
9583                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9584                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9585                 {
9586                         pic16_loadFSR0( result );  // patch 10
9587                 } else {
9588                         // set up FSR0 with address of result
9589                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9590                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9591                 }
9592
9593         }
9594 //      else
9595 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9596
9597         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9598
9599         /* if bitfield then unpack the bits */
9600         if (IS_BITFIELD(resetype)) {
9601                 genPackBits (resetype, right, NULL, POINTER);
9602         } else {
9603                 /* we have can just get the values */
9604           int size = AOP_SIZE(right);
9605           int offset = 0 ;    
9606
9607                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9608                 while (size--) {
9609                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9610                         if (*l == '@' ) {
9611                                 //MOVA(l);
9612                                 //pic16_emitcode("mov","@%s,a",rname);
9613                                 pic16_emitcode("movf","indf0,w ;1");
9614                         } else {
9615
9616                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9617                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9618                                         if (size) {                                                                     // 
9619                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9620                                         } else {                                                                        // 
9621                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9622                                         }                                                                               // 
9623                                 } else { // no literal                                                                  // 
9624                                         if(size) {                                                                      // 
9625                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9626                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9627                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9628                                         } else {                                                                        // 
9629                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9630                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9631                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9632                                         }                                                                               //
9633                                 }                                                                                       // patch 10
9634                         }
9635                         offset++;
9636                 }
9637         }
9638
9639         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9640         /* now some housekeeping stuff */
9641         if (aop) {
9642                 /* we had to allocate for this iCode */
9643                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9644         } else { 
9645                 /* we did not allocate which means left
9646                  * already in a pointer register, then
9647                  * if size > 0 && this could be used again
9648                  * we have to point it back to where it 
9649                  * belongs */
9650                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9651                 if (AOP_SIZE(right) > 1
9652                         && !OP_SYMBOL(result)->remat
9653                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9654                                 || ic->depth )) {
9655
9656                   int size = AOP_SIZE(right) - 1;
9657
9658                         while (size--)
9659                                 pic16_emitcode("decf","fsr0,f");
9660                         //pic16_emitcode("dec","%s",rname);
9661                 }
9662         }
9663
9664         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9665         /* done */
9666 //release:
9667         pic16_freeAsmop(right,NULL,ic,TRUE);
9668         pic16_freeAsmop(result,NULL,ic,TRUE);
9669 }
9670
9671 /*-----------------------------------------------------------------*/
9672 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9673 /*-----------------------------------------------------------------*/
9674 static void genPagedPointerSet (operand *right,
9675                                operand *result, 
9676                                iCode *ic)
9677 {
9678     asmop *aop = NULL;
9679     regs *preg = NULL ;
9680     char *rname , *l;
9681     sym_link *retype;
9682        
9683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9684
9685     retype= getSpec(operandType(right));
9686     
9687     pic16_aopOp(result,ic,FALSE);
9688     
9689     /* if the value is already in a pointer register
9690        then don't need anything more */
9691     if (!AOP_INPREG(AOP(result))) {
9692         /* otherwise get a free pointer register */
9693         aop = newAsmop(0);
9694         preg = getFreePtr(ic,&aop,FALSE);
9695         pic16_emitcode("mov","%s,%s",
9696                 preg->name,
9697                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9698         rname = preg->name ;
9699     } else
9700         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9701     
9702     pic16_freeAsmop(result,NULL,ic,TRUE);
9703     pic16_aopOp (right,ic,FALSE);
9704
9705     /* if bitfield then unpack the bits */
9706     if (IS_BITFIELD(retype)) 
9707         genPackBits (retype,right,rname,PPOINTER);
9708     else {
9709         /* we have can just get the values */
9710         int size = AOP_SIZE(right);
9711         int offset = 0 ;        
9712         
9713         while (size--) {
9714             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9715             
9716             MOVA(l);
9717             pic16_emitcode("movx","@%s,a",rname);
9718
9719             if (size)
9720                 pic16_emitcode("inc","%s",rname);
9721
9722             offset++;
9723         }
9724     }
9725     
9726     /* now some housekeeping stuff */
9727     if (aop) {
9728         /* we had to allocate for this iCode */
9729         pic16_freeAsmop(NULL,aop,ic,TRUE);
9730     } else { 
9731         /* we did not allocate which means left
9732            already in a pointer register, then
9733            if size > 0 && this could be used again
9734            we have to point it back to where it 
9735            belongs */
9736         if (AOP_SIZE(right) > 1 &&
9737             !OP_SYMBOL(result)->remat &&
9738             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9739               ic->depth )) {
9740             int size = AOP_SIZE(right) - 1;
9741             while (size--)
9742                 pic16_emitcode("dec","%s",rname);
9743         }
9744     }
9745
9746     /* done */
9747     pic16_freeAsmop(right,NULL,ic,TRUE);
9748     
9749         
9750 }
9751
9752 /*-----------------------------------------------------------------*/
9753 /* genFarPointerSet - set value from far space                     */
9754 /*-----------------------------------------------------------------*/
9755 static void genFarPointerSet (operand *right,
9756                               operand *result, iCode *ic)
9757 {
9758     int size, offset ;
9759     sym_link *retype = getSpec(operandType(right));
9760
9761     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9762     pic16_aopOp(result,ic,FALSE);
9763
9764     /* if the operand is already in dptr 
9765     then we do nothing else we move the value to dptr */
9766     if (AOP_TYPE(result) != AOP_STR) {
9767         /* if this is remateriazable */
9768         if (AOP_TYPE(result) == AOP_IMMD)
9769             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9770         else { /* we need to get it byte by byte */
9771             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9772             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9773             if (options.model == MODEL_FLAT24)
9774             {
9775                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9776             }
9777         }
9778     }
9779     /* so dptr know contains the address */
9780     pic16_freeAsmop(result,NULL,ic,TRUE);
9781     pic16_aopOp(right,ic,FALSE);
9782
9783     /* if bit then unpack */
9784     if (IS_BITFIELD(retype)) 
9785         genPackBits(retype,right,"dptr",FPOINTER);
9786     else {
9787         size = AOP_SIZE(right);
9788         offset = 0 ;
9789
9790         while (size--) {
9791             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9792             MOVA(l);
9793             pic16_emitcode("movx","@dptr,a");
9794             if (size)
9795                 pic16_emitcode("inc","dptr");
9796         }
9797     }
9798
9799     pic16_freeAsmop(right,NULL,ic,TRUE);
9800 }
9801
9802 /*-----------------------------------------------------------------*/
9803 /* genGenPointerSet - set value from generic pointer space         */
9804 /*-----------------------------------------------------------------*/
9805 static void genGenPointerSet (operand *right,
9806                               operand *result, iCode *ic)
9807 {
9808         int i, size, offset, lit;
9809         sym_link *retype = getSpec(operandType(right));
9810
9811         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9812
9813         pic16_aopOp(result,ic,FALSE);
9814         pic16_aopOp(right,ic,FALSE);
9815         size = AOP_SIZE(right);
9816         offset = 0;
9817
9818         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9819
9820         /* if the operand is already in dptr 
9821                 then we do nothing else we move the value to dptr */
9822         if (AOP_TYPE(result) != AOP_STR) {
9823                 /* if this is remateriazable */
9824                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9825                 // WARNING: anythig until "else" is untested!
9826                 if (AOP_TYPE(result) == AOP_IMMD) {
9827                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9828                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9829                         // load FSR0 from immediate
9830                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9831                         offset = 0;
9832                         while(size--) {
9833                                 if(size) {
9834                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9835                                 } else {
9836                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9837                                 }
9838                                 offset++;
9839                         }
9840                         goto release;
9841                 }
9842                 else { /* we need to get it byte by byte */
9843                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9844                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9845
9846                         // set up FSR0 with address of result
9847                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9848                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9849
9850                         /* hack hack! see if this the FSR. If so don't load W */
9851                         if(AOP_TYPE(right) != AOP_ACC) {
9852
9853                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9854
9855                                 if(AOP_TYPE(right) == AOP_LIT)
9856                                 {
9857                                         // copy literal
9858                                         // note: pic16_popGet handles sign extension
9859                                         for(i=0;i<size;i++) {
9860                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
9861                                                 if(i < size-1)
9862                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
9863                                                 else
9864                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9865                                         }
9866                                 } else {
9867                                         // copy regs
9868
9869                                         for(i=0;i<size;i++) {
9870                                                 if(i < size-1)
9871                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9872                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
9873                                                 else
9874                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9875                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
9876                                         }
9877                                 }
9878                                 goto release;
9879                         } 
9880                         // right = ACC
9881                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9882                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9883                         goto release;
9884         } // if (AOP_TYPE(result) != AOP_IMMD)
9885
9886         } // if (AOP_TYPE(result) != AOP_STR)
9887         /* so dptr know contains the address */
9888
9889
9890         /* if bit then unpack */
9891         if (IS_BITFIELD(retype)) 
9892                 genPackBits(retype,right,"dptr",GPOINTER);
9893         else {
9894                 size = AOP_SIZE(right);
9895                 offset = 0 ;
9896
9897                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9898
9899                 // set up FSR0 with address of result
9900                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9901                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9902         
9903                 while (size--) {
9904                         if (AOP_TYPE(right) == AOP_LIT) {
9905                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9906                                 if (size) {
9907                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9908                                 } else {
9909                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9910                                 }
9911                         } else { // no literal
9912                                 if(size) {
9913                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9914                                 } else {
9915                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9916                                 }
9917                         }
9918                         offset++;
9919                 }
9920         }
9921
9922         release:
9923         pic16_freeAsmop(right,NULL,ic,TRUE);
9924         pic16_freeAsmop(result,NULL,ic,TRUE);
9925 }
9926
9927 /*-----------------------------------------------------------------*/
9928 /* genPointerSet - stores the value into a pointer location        */
9929 /*-----------------------------------------------------------------*/
9930 static void genPointerSet (iCode *ic)
9931 {    
9932     operand *right, *result ;
9933     sym_link *type, *etype;
9934     int p_type;
9935
9936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9937
9938     right = IC_RIGHT(ic);
9939     result = IC_RESULT(ic) ;
9940
9941     /* depending on the type of pointer we need to
9942     move it to the correct pointer register */
9943     type = operandType(result);
9944     etype = getSpec(type);
9945     /* if left is of type of pointer then it is simple */
9946     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9947         p_type = DCL_TYPE(type);
9948     }
9949     else {
9950         /* we have to go by the storage class */
9951         p_type = PTR_TYPE(SPEC_OCLS(etype));
9952
9953 /*      if (SPEC_OCLS(etype)->codesp ) { */
9954 /*          p_type = CPOINTER ;  */
9955 /*      } */
9956 /*      else */
9957 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9958 /*              p_type = FPOINTER ; */
9959 /*          else */
9960 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9961 /*                  p_type = PPOINTER ; */
9962 /*              else */
9963 /*                  if (SPEC_OCLS(etype) == idata ) */
9964 /*                      p_type = IPOINTER ; */
9965 /*                  else */
9966 /*                      p_type = POINTER ; */
9967     }
9968
9969     /* now that we have the pointer type we assign
9970     the pointer values */
9971     switch (p_type) {
9972
9973     case POINTER:
9974     case IPOINTER:
9975         genNearPointerSet (right,result,ic);
9976         break;
9977
9978     case PPOINTER:
9979         genPagedPointerSet (right,result,ic);
9980         break;
9981
9982     case FPOINTER:
9983         genFarPointerSet (right,result,ic);
9984         break;
9985
9986     case GPOINTER:
9987         genGenPointerSet (right,result,ic);
9988         break;
9989
9990     default:
9991       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9992               "genPointerSet: illegal pointer type");
9993     }
9994 }
9995
9996 /*-----------------------------------------------------------------*/
9997 /* genIfx - generate code for Ifx statement                        */
9998 /*-----------------------------------------------------------------*/
9999 static void genIfx (iCode *ic, iCode *popIc)
10000 {
10001   operand *cond = IC_COND(ic);
10002   int isbit =0;
10003
10004   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10005
10006   pic16_aopOp(cond,ic,FALSE);
10007
10008   /* get the value into acc */
10009   if (AOP_TYPE(cond) != AOP_CRY)
10010     pic16_toBoolean(cond);
10011   else
10012     isbit = 1;
10013   /* the result is now in the accumulator */
10014   pic16_freeAsmop(cond,NULL,ic,TRUE);
10015
10016   /* if there was something to be popped then do it */
10017   if (popIc)
10018     genIpop(popIc);
10019
10020   /* if the condition is  a bit variable */
10021   if (isbit && IS_ITEMP(cond) && 
10022       SPIL_LOC(cond)) {
10023     genIfxJump(ic,SPIL_LOC(cond)->rname);
10024     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10025   }
10026   else {
10027     if (isbit && !IS_ITEMP(cond))
10028       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10029     else
10030       genIfxJump(ic,"a");
10031   }
10032   ic->generated = 1;
10033
10034 }
10035
10036 /*-----------------------------------------------------------------*/
10037 /* genAddrOf - generates code for address of                       */
10038 /*-----------------------------------------------------------------*/
10039 static void genAddrOf (iCode *ic)
10040 {
10041   operand *result, *left;
10042   int size;
10043   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10044   pCodeOp *pcop0, *pcop1, *pcop2;
10045
10046         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10047
10048         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10049         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10050
10051         sym = OP_SYMBOL( left );
10052
10053         size = AOP_SIZE(IC_RESULT(ic));
10054
10055         if(pic16_debug_verbose) {
10056                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10057                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10058         }
10059         
10060         /* Assume that what we want the address of is in data space
10061          * since there is no stack on the PIC, yet! -- VR */
10062         /* low */
10063         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10064
10065         /* high */
10066         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10067         
10068         /* upper */
10069         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10070         
10071
10072         if (size == 3) {
10073                 pic16_emitpcode(POC_MOVLW, pcop0);
10074                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10075                 pic16_emitpcode(POC_MOVLW, pcop1);
10076                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10077                 pic16_emitpcode(POC_MOVLW, pcop2);
10078                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10079         } else
10080         if (size == 2) {
10081                 pic16_emitpcode(POC_MOVLW, pcop0);
10082                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10083                 pic16_emitpcode(POC_MOVLW, pcop1);
10084                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10085         } else {
10086                 pic16_emitpcode(POC_MOVLW, pcop0);
10087                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10088         }
10089
10090         pic16_freeAsmop(result,NULL,ic,TRUE);
10091         pic16_freeAsmop(left, NULL, ic, FALSE);
10092 }
10093
10094
10095 #if 0
10096 /*-----------------------------------------------------------------*/
10097 /* genFarFarAssign - assignment when both are in far space         */
10098 /*-----------------------------------------------------------------*/
10099 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10100 {
10101     int size = AOP_SIZE(right);
10102     int offset = 0;
10103     char *l ;
10104     /* first push the right side on to the stack */
10105     while (size--) {
10106         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10107         MOVA(l);
10108         pic16_emitcode ("push","acc");
10109     }
10110     
10111     pic16_freeAsmop(right,NULL,ic,FALSE);
10112     /* now assign DPTR to result */
10113     pic16_aopOp(result,ic,FALSE);
10114     size = AOP_SIZE(result);
10115     while (size--) {
10116         pic16_emitcode ("pop","acc");
10117         pic16_aopPut(AOP(result),"a",--offset);
10118     }
10119     pic16_freeAsmop(result,NULL,ic,FALSE);
10120         
10121 }
10122 #endif
10123
10124 /*-----------------------------------------------------------------*/
10125 /* genAssign - generate code for assignment                        */
10126 /*-----------------------------------------------------------------*/
10127 static void genAssign (iCode *ic)
10128 {
10129   operand *result, *right;
10130   int size, offset,know_W;
10131   unsigned long lit = 0L;
10132
10133   result = IC_RESULT(ic);
10134   right  = IC_RIGHT(ic) ;
10135
10136   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10137   
10138   /* if they are the same */
10139   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10140     return ;
10141
10142   pic16_aopOp(right,ic,FALSE);
10143   pic16_aopOp(result,ic,TRUE);
10144
10145   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10146
10147   /* if they are the same registers */
10148   if (pic16_sameRegs(AOP(right),AOP(result)))
10149     goto release;
10150
10151   /* if the result is a bit */
10152   if (AOP_TYPE(result) == AOP_CRY) {
10153     /* if the right size is a literal then
10154        we know what the value is */
10155     if (AOP_TYPE(right) == AOP_LIT) {
10156           
10157       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10158                   pic16_popGet(AOP(result),0));
10159
10160       if (((int) operandLitValue(right))) 
10161         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10162                        AOP(result)->aopu.aop_dir,
10163                        AOP(result)->aopu.aop_dir);
10164       else
10165         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10166                        AOP(result)->aopu.aop_dir,
10167                        AOP(result)->aopu.aop_dir);
10168       goto release;
10169     }
10170
10171     /* the right is also a bit variable */
10172     if (AOP_TYPE(right) == AOP_CRY) {
10173       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10174       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10175       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10176
10177       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10178                      AOP(result)->aopu.aop_dir,
10179                      AOP(result)->aopu.aop_dir);
10180       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10181                      AOP(right)->aopu.aop_dir,
10182                      AOP(right)->aopu.aop_dir);
10183       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10184                      AOP(result)->aopu.aop_dir,
10185                      AOP(result)->aopu.aop_dir);
10186       goto release ;
10187     }
10188
10189     /* we need to or */
10190     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10191     pic16_toBoolean(right);
10192     emitSKPZ;
10193     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10194     //pic16_aopPut(AOP(result),"a",0);
10195     goto release ;
10196   }
10197
10198   /* bit variables done */
10199   /* general case */
10200   size = AOP_SIZE(result);
10201   offset = 0 ;
10202   if(AOP_TYPE(right) == AOP_LIT)
10203     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10204
10205 /* VR - What is this?! */
10206   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10207   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10208     if(aopIdx(AOP(result),0) == 4) {
10209   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10210       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10211       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10212       goto release;
10213     } else
10214       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10215   }
10216
10217   know_W=-1;
10218   while (size--) {
10219   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10220     if(AOP_TYPE(right) == AOP_LIT) {
10221       if(lit&0xff) {
10222         if(know_W != (lit&0xff))
10223           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10224         know_W = lit&0xff;
10225         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10226       } else
10227         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10228
10229       lit >>= 8;
10230
10231     } else if (AOP_TYPE(right) == AOP_CRY) {
10232       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10233       if(offset == 0) {
10234         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10235         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10236       }
10237     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10238         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10239         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10240     } else {
10241   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10242
10243 #if 1
10244         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10245            normally should work, but mind that the W register live range
10246            is not checked, so if the code generator assumes that the W
10247            is already loaded after such a pair, wrong code will be generated.
10248            
10249            Checking the live range is the next step.
10250            This is experimental code yet and has not been fully tested yet.
10251            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10252            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10253            
10254         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10255 #else   
10256         /* This is the old code, which is assumed(?!) that works fine(!?) */
10257
10258         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10259         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10260 #endif
10261     }
10262             
10263     offset++;
10264   }
10265
10266     
10267  release:
10268   pic16_freeAsmop (right,NULL,ic,FALSE);
10269   pic16_freeAsmop (result,NULL,ic,TRUE);
10270 }   
10271
10272 /*-----------------------------------------------------------------*/
10273 /* genJumpTab - generates code for jump table                       */
10274 /*-----------------------------------------------------------------*/
10275 static void genJumpTab (iCode *ic)
10276 {
10277     symbol *jtab;
10278     char *l;
10279
10280     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10281
10282     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10283     /* get the condition into accumulator */
10284     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10285     MOVA(l);
10286     /* multiply by three */
10287     pic16_emitcode("add","a,acc");
10288     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10289
10290     jtab = newiTempLabel(NULL);
10291     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10292     pic16_emitcode("jmp","@a+dptr");
10293     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10294
10295     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10296     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10297     emitSKPNC;
10298     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10299     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10300     pic16_emitpLabel(jtab->key);
10301
10302     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10303
10304     /* now generate the jump labels */
10305     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10306          jtab = setNextItem(IC_JTLABELS(ic))) {
10307         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10308         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10309         
10310     }
10311
10312 }
10313
10314 /*-----------------------------------------------------------------*/
10315 /* genMixedOperation - gen code for operators between mixed types  */
10316 /*-----------------------------------------------------------------*/
10317 /*
10318   TSD - Written for the PIC port - but this unfortunately is buggy.
10319   This routine is good in that it is able to efficiently promote 
10320   types to different (larger) sizes. Unfortunately, the temporary
10321   variables that are optimized out by this routine are sometimes
10322   used in other places. So until I know how to really parse the 
10323   iCode tree, I'm going to not be using this routine :(.
10324 */
10325 static int genMixedOperation (iCode *ic)
10326 {
10327 #if 0
10328   operand *result = IC_RESULT(ic);
10329   sym_link *ctype = operandType(IC_LEFT(ic));
10330   operand *right = IC_RIGHT(ic);
10331   int ret = 0;
10332   int big,small;
10333   int offset;
10334
10335   iCode *nextic;
10336   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10337
10338   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10339
10340   nextic = ic->next;
10341   if(!nextic)
10342     return 0;
10343
10344   nextright = IC_RIGHT(nextic);
10345   nextleft  = IC_LEFT(nextic);
10346   nextresult = IC_RESULT(nextic);
10347
10348   pic16_aopOp(right,ic,FALSE);
10349   pic16_aopOp(result,ic,FALSE);
10350   pic16_aopOp(nextright,  nextic, FALSE);
10351   pic16_aopOp(nextleft,   nextic, FALSE);
10352   pic16_aopOp(nextresult, nextic, FALSE);
10353
10354   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10355
10356     operand *t = right;
10357     right = nextright;
10358     nextright = t; 
10359
10360     pic16_emitcode(";remove right +","");
10361
10362   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10363 /*
10364     operand *t = right;
10365     right = nextleft;
10366     nextleft = t; 
10367 */
10368     pic16_emitcode(";remove left +","");
10369   } else
10370     return 0;
10371
10372   big = AOP_SIZE(nextleft);
10373   small = AOP_SIZE(nextright);
10374
10375   switch(nextic->op) {
10376
10377   case '+':
10378     pic16_emitcode(";optimize a +","");
10379     /* if unsigned or not an integral type */
10380     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10381       pic16_emitcode(";add a bit to something","");
10382     } else {
10383
10384       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10385
10386       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10387         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10388         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10389       } else
10390         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10391
10392       offset = 0;
10393       while(--big) {
10394
10395         offset++;
10396
10397         if(--small) {
10398           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10399             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10400             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10401           }
10402
10403           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10404           emitSKPNC;
10405           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10406                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10407                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10408           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10409           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10410
10411         } else {
10412           pic16_emitcode("rlf","known_zero,w");
10413
10414           /*
10415             if right is signed
10416               btfsc  right,7
10417                addlw ff
10418           */
10419           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10420             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10421             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10422           } else {
10423             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10424           }
10425         }
10426       }
10427       ret = 1;
10428     }
10429   }
10430   ret = 1;
10431
10432 release:
10433   pic16_freeAsmop(right,NULL,ic,TRUE);
10434   pic16_freeAsmop(result,NULL,ic,TRUE);
10435   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10436   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10437   if(ret)
10438     nextic->generated = 1;
10439
10440   return ret;
10441 #else
10442   return 0;
10443 #endif
10444 }
10445 /*-----------------------------------------------------------------*/
10446 /* genCast - gen code for casting                                  */
10447 /*-----------------------------------------------------------------*/
10448 static void genCast (iCode *ic)
10449 {
10450   operand *result = IC_RESULT(ic);
10451   sym_link *ctype = operandType(IC_LEFT(ic));
10452   sym_link *rtype = operandType(IC_RIGHT(ic));
10453   operand *right = IC_RIGHT(ic);
10454   int size, offset ;
10455
10456         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10457         /* if they are equivalent then do nothing */
10458         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10459                 return ;
10460
10461         pic16_aopOp(right,ic,FALSE) ;
10462         pic16_aopOp(result,ic,FALSE);
10463
10464         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10465
10466         /* if the result is a bit */
10467         if (AOP_TYPE(result) == AOP_CRY) {
10468         
10469                 /* if the right size is a literal then
10470                  * we know what the value is */
10471                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10472
10473                 if (AOP_TYPE(right) == AOP_LIT) {
10474                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10475                                 pic16_popGet(AOP(result),0));
10476
10477                         if (((int) operandLitValue(right))) 
10478                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10479                                         AOP(result)->aopu.aop_dir,
10480                                         AOP(result)->aopu.aop_dir);
10481                         else
10482                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10483                                         AOP(result)->aopu.aop_dir,
10484                                         AOP(result)->aopu.aop_dir);
10485                         goto release;
10486                 }
10487
10488                 /* the right is also a bit variable */
10489                 if (AOP_TYPE(right) == AOP_CRY) {
10490                         emitCLRC;
10491                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10492
10493                         pic16_emitcode("clrc","");
10494                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10495                                 AOP(right)->aopu.aop_dir,
10496                                 AOP(right)->aopu.aop_dir);
10497                         pic16_aopPut(AOP(result),"c",0);
10498                         goto release ;
10499                 }
10500
10501                 /* we need to or */
10502                 if (AOP_TYPE(right) == AOP_REG) {
10503                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10504                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10505                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10506                 }
10507                 pic16_toBoolean(right);
10508                 pic16_aopPut(AOP(result),"a",0);
10509                 goto release ;
10510         }
10511
10512         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10513           int offset = 1;
10514
10515                 size = AOP_SIZE(result);
10516
10517                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10518
10519                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10520                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10521                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10522
10523                 while (size--)
10524                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10525
10526                 goto release;
10527         }
10528
10529         /* if they are the same size : or less */
10530         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10531
10532                 /* if they are in the same place */
10533                 if (pic16_sameRegs(AOP(right),AOP(result)))
10534                         goto release;
10535
10536                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10537 #if 0
10538                 if (IS_PTR_CONST(rtype))
10539 #else
10540                 if (IS_CODEPTR(rtype))
10541 #endif
10542                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10543
10544 #if 0
10545                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10546 #else
10547                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10548 #endif
10549                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10550
10551 #if 0
10552                 if(AOP_TYPE(right) == AOP_IMMD) {
10553                   pCodeOp *pcop0, *pcop1, *pcop2;
10554                   symbol *sym = OP_SYMBOL( right );
10555
10556                         size = AOP_SIZE(result);
10557                         /* low */
10558                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10559                         /* high */
10560                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10561                         /* upper */
10562                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10563         
10564                         if (size == 3) {
10565                                 pic16_emitpcode(POC_MOVLW, pcop0);
10566                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10567                                 pic16_emitpcode(POC_MOVLW, pcop1);
10568                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10569                                 pic16_emitpcode(POC_MOVLW, pcop2);
10570                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10571                         } else
10572                         if (size == 2) {
10573                                 pic16_emitpcode(POC_MOVLW, pcop0);
10574                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10575                                 pic16_emitpcode(POC_MOVLW, pcop1);
10576                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10577                         } else {
10578                                 pic16_emitpcode(POC_MOVLW, pcop0);
10579                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10580                         }
10581                 } else
10582 #endif
10583                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10584                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10585                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10586                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10587                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10588                         if(AOP_SIZE(result) <2)
10589                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10590                 } else {
10591                         /* if they in different places then copy */
10592                         size = AOP_SIZE(result);
10593                         offset = 0 ;
10594                         while (size--) {
10595                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10596                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10597                                 offset++;
10598                         }
10599                 }
10600                 goto release;
10601         }
10602
10603         /* if the result is of type pointer */
10604         if (IS_PTR(ctype)) {
10605           int p_type;
10606           sym_link *type = operandType(right);
10607           sym_link *etype = getSpec(type);
10608
10609                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10610
10611                 /* pointer to generic pointer */
10612                 if (IS_GENPTR(ctype)) {
10613                   char *l = zero;
10614             
10615                         if (IS_PTR(type)) 
10616                                 p_type = DCL_TYPE(type);
10617                         else {
10618                 /* we have to go by the storage class */
10619                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10620
10621 /*              if (SPEC_OCLS(etype)->codesp )  */
10622 /*                  p_type = CPOINTER ;  */
10623 /*              else */
10624 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10625 /*                      p_type = FPOINTER ; */
10626 /*                  else */
10627 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10628 /*                          p_type = PPOINTER; */
10629 /*                      else */
10630 /*                          if (SPEC_OCLS(etype) == idata ) */
10631 /*                              p_type = IPOINTER ; */
10632 /*                          else */
10633 /*                              p_type = POINTER ; */
10634             }
10635                 
10636             /* the first two bytes are known */
10637       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10638             size = GPTRSIZE - 1; 
10639             offset = 0 ;
10640             while (size--) {
10641               if(offset < AOP_SIZE(right)) {
10642       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10643                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10644                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10645                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10646                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10647                 } else { 
10648                   pic16_aopPut(AOP(result),
10649                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10650                          offset);
10651                 }
10652               } else 
10653                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10654               offset++;
10655             }
10656             /* the last byte depending on type */
10657             switch (p_type) {
10658             case IPOINTER:
10659             case POINTER:
10660                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10661                 break;
10662             case FPOINTER:
10663               pic16_emitcode(";BUG!? ","%d",__LINE__);
10664                 l = one;
10665                 break;
10666             case CPOINTER:
10667               pic16_emitcode(";BUG!? ","%d",__LINE__);
10668                 l = "#0x02";
10669                 break;                          
10670             case PPOINTER:
10671               pic16_emitcode(";BUG!? ","%d",__LINE__);
10672                 l = "#0x03";
10673                 break;
10674                 
10675             default:
10676                 /* this should never happen */
10677                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10678                        "got unknown pointer type");
10679                 exit(1);
10680             }
10681             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10682             goto release ;
10683         }
10684         
10685         /* just copy the pointers */
10686         size = AOP_SIZE(result);
10687         offset = 0 ;
10688         while (size--) {
10689             pic16_aopPut(AOP(result),
10690                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10691                    offset);
10692             offset++;
10693         }
10694         goto release ;
10695     }
10696     
10697
10698
10699     /* so we now know that the size of destination is greater
10700     than the size of the source.
10701     Now, if the next iCode is an operator then we might be
10702     able to optimize the operation without performing a cast.
10703     */
10704     if(genMixedOperation(ic))
10705       goto release;
10706
10707     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10708     
10709     /* we move to result for the size of source */
10710     size = AOP_SIZE(right);
10711     offset = 0 ;
10712     while (size--) {
10713       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10714       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10715       offset++;
10716     }
10717
10718     /* now depending on the sign of the destination */
10719     size = AOP_SIZE(result) - AOP_SIZE(right);
10720     /* if unsigned or not an integral type */
10721     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10722       while (size--)
10723         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10724     } else {
10725       /* we need to extend the sign :( */
10726
10727       if(size == 1) {
10728         /* Save one instruction of casting char to int */
10729         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10730         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10731         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10732       } else {
10733         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10734
10735         if(offset)
10736           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10737         else
10738           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10739         
10740         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10741
10742         while (size--)
10743           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10744       }
10745     }
10746
10747 release:
10748     pic16_freeAsmop(right,NULL,ic,TRUE);
10749     pic16_freeAsmop(result,NULL,ic,TRUE);
10750
10751 }
10752
10753 /*-----------------------------------------------------------------*/
10754 /* genDjnz - generate decrement & jump if not zero instrucion      */
10755 /*-----------------------------------------------------------------*/
10756 static int genDjnz (iCode *ic, iCode *ifx)
10757 {
10758     symbol *lbl, *lbl1;
10759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10760
10761     if (!ifx)
10762         return 0;
10763     
10764     /* if the if condition has a false label
10765        then we cannot save */
10766     if (IC_FALSE(ifx))
10767         return 0;
10768
10769     /* if the minus is not of the form 
10770        a = a - 1 */
10771     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10772         !IS_OP_LITERAL(IC_RIGHT(ic)))
10773         return 0;
10774
10775     if (operandLitValue(IC_RIGHT(ic)) != 1)
10776         return 0;
10777
10778     /* if the size of this greater than one then no
10779        saving */
10780     if (getSize(operandType(IC_RESULT(ic))) > 1)
10781         return 0;
10782
10783     /* otherwise we can save BIG */
10784     lbl = newiTempLabel(NULL);
10785     lbl1= newiTempLabel(NULL);
10786
10787     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10788     
10789     if (IS_AOP_PREG(IC_RESULT(ic))) {
10790         pic16_emitcode("dec","%s",
10791                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10792         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10793         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10794     } else {    
10795
10796
10797       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10798       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10799
10800       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10801       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10802
10803     }
10804 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10805 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10806 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10807 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10808
10809     
10810     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10811     ifx->generated = 1;
10812     return 1;
10813 }
10814
10815 /*-----------------------------------------------------------------*/
10816 /* genReceive - generate code for a receive iCode                  */
10817 /*-----------------------------------------------------------------*/
10818 static void genReceive (iCode *ic)
10819 {    
10820         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10821
10822         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10823                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10824                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10825
10826           int size = getSize(operandType(IC_RESULT(ic)));
10827           int offset =  pic16_fReturnSizePic - size;
10828
10829                 while (size--) {
10830                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10831                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10832                         offset++;
10833                 }
10834
10835                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10836
10837                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10838                 size = AOP_SIZE(IC_RESULT(ic));
10839                 offset = 0;
10840                 while (size--) {
10841                         pic16_emitcode ("pop","acc");
10842                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10843                 }
10844         } else {
10845                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10846
10847                 _G.accInUse++;
10848                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10849                 _G.accInUse--;
10850                 assignResultValue(IC_RESULT(ic), 0);
10851         }
10852
10853         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10854 }
10855
10856 /*-----------------------------------------------------------------*/
10857 /* genDummyRead - generate code for dummy read of volatiles        */
10858 /*-----------------------------------------------------------------*/
10859 static void
10860 genDummyRead (iCode * ic)
10861 {
10862   pic16_emitcode ("; genDummyRead","");
10863   pic16_emitcode ("; not implemented","");
10864
10865   ic = ic;
10866 }
10867
10868 /*-----------------------------------------------------------------*/
10869 /* genpic16Code - generate code for pic16 based controllers        */
10870 /*-----------------------------------------------------------------*/
10871 /*
10872  * At this point, ralloc.c has gone through the iCode and attempted
10873  * to optimize in a way suitable for a PIC. Now we've got to generate
10874  * PIC instructions that correspond to the iCode.
10875  *
10876  * Once the instructions are generated, we'll pass through both the
10877  * peep hole optimizer and the pCode optimizer.
10878  *-----------------------------------------------------------------*/
10879
10880 void genpic16Code (iCode *lic)
10881 {
10882     iCode *ic;
10883     int cln = 0;
10884
10885     lineHead = lineCurr = NULL;
10886
10887     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10888     pic16_addpBlock(pb);
10889
10890 #if 0
10891     /* if debug information required */
10892     if (options.debug && currFunc) {
10893       if (currFunc) {
10894         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10895         _G.debugLine = 1;
10896         if (IS_STATIC(currFunc->etype)) {
10897           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10898           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10899         } else {
10900           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10901           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10902         }
10903         _G.debugLine = 0;
10904       }
10905     }
10906 #endif
10907
10908     for (ic = lic ; ic ; ic = ic->next ) {
10909
10910       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10911         if ( cln != ic->lineno ) {
10912             if ( options.debug ) {
10913                 _G.debugLine = 1;
10914                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10915                          FileBaseName(ic->filename),ic->lineno,
10916                          ic->level,ic->block);
10917                 _G.debugLine = 0;
10918             }
10919             
10920             if(!options.noCcodeInAsm) {
10921                 pic16_addpCode2pBlock(pb,
10922                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10923                                 printCLine(ic->filename, ic->lineno)));
10924             }
10925
10926             cln = ic->lineno ;
10927         }
10928         
10929         if(options.iCodeInAsm) {
10930                 /* insert here code to print iCode as comment */
10931                 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10932         }
10933         
10934         /* if the result is marked as
10935            spilt and rematerializable or code for
10936            this has already been generated then
10937            do nothing */
10938         if (resultRemat(ic) || ic->generated ) 
10939             continue ;
10940         
10941         /* depending on the operation */
10942         switch (ic->op) {
10943         case '!' :
10944             pic16_genNot(ic);
10945             break;
10946             
10947         case '~' :
10948             pic16_genCpl(ic);
10949             break;
10950             
10951         case UNARYMINUS:
10952             genUminus (ic);
10953             break;
10954             
10955         case IPUSH:
10956             genIpush (ic);
10957             break;
10958             
10959         case IPOP:
10960             /* IPOP happens only when trying to restore a 
10961                spilt live range, if there is an ifx statement
10962                following this pop then the if statement might
10963                be using some of the registers being popped which
10964                would destroy the contents of the register so
10965                we need to check for this condition and handle it */
10966             if (ic->next            && 
10967                 ic->next->op == IFX &&
10968                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10969                 genIfx (ic->next,ic);
10970             else
10971                 genIpop (ic);
10972             break; 
10973             
10974         case CALL:
10975             genCall (ic);
10976             break;
10977             
10978         case PCALL:
10979             genPcall (ic);
10980             break;
10981             
10982         case FUNCTION:
10983             genFunction (ic);
10984             break;
10985             
10986         case ENDFUNCTION:
10987             genEndFunction (ic);
10988             break;
10989             
10990         case RETURN:
10991             genRet (ic);
10992             break;
10993             
10994         case LABEL:
10995             genLabel (ic);
10996             break;
10997             
10998         case GOTO:
10999             genGoto (ic);
11000             break;
11001             
11002         case '+' :
11003             pic16_genPlus (ic) ;
11004             break;
11005             
11006         case '-' :
11007             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11008                 pic16_genMinus (ic);
11009             break;
11010             
11011         case '*' :
11012             genMult (ic);
11013             break;
11014             
11015         case '/' :
11016             genDiv (ic) ;
11017             break;
11018             
11019         case '%' :
11020             genMod (ic);
11021             break;
11022             
11023         case '>' :
11024             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11025             break;
11026             
11027         case '<' :
11028             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11029             break;
11030             
11031         case LE_OP:
11032         case GE_OP:
11033         case NE_OP:
11034             
11035             /* note these two are xlated by algebraic equivalence
11036                during parsing SDCC.y */
11037             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11038                    "got '>=' or '<=' shouldn't have come here");
11039             break;      
11040             
11041         case EQ_OP:
11042             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11043             break;          
11044             
11045         case AND_OP:
11046             genAndOp (ic);
11047             break;
11048             
11049         case OR_OP:
11050             genOrOp (ic);
11051             break;
11052             
11053         case '^' :
11054             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11055             break;
11056             
11057         case '|' :
11058                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11059             break;
11060             
11061         case BITWISEAND:
11062             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11063             break;
11064             
11065         case INLINEASM:
11066             genInline (ic);
11067             break;
11068             
11069         case RRC:
11070             genRRC (ic);
11071             break;
11072             
11073         case RLC:
11074             genRLC (ic);
11075             break;
11076             
11077         case GETHBIT:
11078             genGetHbit (ic);
11079             break;
11080             
11081         case LEFT_OP:
11082             genLeftShift (ic);
11083             break;
11084             
11085         case RIGHT_OP:
11086             genRightShift (ic);
11087             break;
11088             
11089         case GET_VALUE_AT_ADDRESS:
11090             genPointerGet(ic);
11091             break;
11092             
11093         case '=' :
11094             if (POINTER_SET(ic))
11095                 genPointerSet(ic);
11096             else
11097                 genAssign(ic);
11098             break;
11099             
11100         case IFX:
11101             genIfx (ic,NULL);
11102             break;
11103             
11104         case ADDRESS_OF:
11105             genAddrOf (ic);
11106             break;
11107             
11108         case JUMPTABLE:
11109             genJumpTab (ic);
11110             break;
11111             
11112         case CAST:
11113             genCast (ic);
11114             break;
11115             
11116         case RECEIVE:
11117             genReceive(ic);
11118             break;
11119             
11120         case SEND:
11121             addSet(&_G.sendSet,ic);
11122             break;
11123
11124         case DUMMY_READ_VOLATILE:
11125           genDummyRead (ic);
11126           break;
11127
11128         default :
11129             ic = ic;
11130         }
11131     }
11132
11133
11134     /* now we are ready to call the
11135        peep hole optimizer */
11136     if (!options.nopeep) {
11137       peepHole (&lineHead);
11138     }
11139     /* now do the actual printing */
11140     printLine (lineHead,codeOutFile);
11141
11142 #ifdef PCODE_DEBUG
11143     DFPRINTF((stderr,"printing pBlock\n\n"));
11144     pic16_printpBlock(stdout,pb);
11145 #endif
11146
11147     return;
11148 }
11149