* device/lib/pic16/libsdcc/Makefile: added lregs directory in
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static void mov2f(asmop *dst, asmop *src, int offset);
62 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
63 static pCodeOp *pic16_popRegFromIdx(int rIdx);
64
65 //static int aopIdx (asmop *aop, int offset);
66
67 int pic16_labelOffset=0;
68 extern int pic16_debug_verbose;
69 static int optimized_for_speed = 0;
70 /*
71   hack hack
72
73 */
74
75 /* max_key keeps track of the largest label number used in 
76    a function. This is then used to adjust the label offset
77    for the next function.
78 */
79 static int max_key=0;
80 static int GpsuedoStkPtr=0;
81
82 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
83
84 unsigned int pic16aopLiteral (value *val, int offset);
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
87
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
90
91 static bool is_LitOp(operand *op);
92 static bool is_LitAOp(asmop *aop);
93
94
95 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
96
97 /* this is the down and dirty file with all kinds of 
98    kludgy & hacky stuff. This is what it is all about
99    CODE GENERATION for a specific MCU . some of the
100    routines may be reusable, will have to see */
101
102 static char *zero = "#0x00";
103 static char *one  = "#0x01";
104 //static char *spname = "sp";
105
106
107 /*
108  * Function return value policy (MSB-->LSB):
109  *  8 bits      -> WREG
110  * 16 bits      -> PRODL:WREG
111  * 24 bits      -> PRODH:PRODL:WREG
112  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
113  * >32 bits     -> on stack, and FSR0 points to the beginning
114  *
115  */
116  
117
118 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
119 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
120 static char **fReturn = fReturnpic16;
121
122 static char *accUse[] = {"WREG"};
123
124 //static short rbank = -1;
125
126 static struct {
127     short r0Pushed;
128     short r1Pushed;
129     short fsr0Pushed;
130     short accInUse;
131     short inLine;
132     short debugLine;
133     short nRegsSaved;
134     short ipushRegs;
135     set *sendSet;
136     set *stackRegSet;
137     int interruptvector;
138     int usefastretfie;
139     bitVect *fregsUsed;
140     int stack_lat;                      /* stack offset latency */
141     int resDirect;
142     int useWreg;                        /* flag when WREG is used to pass function parameter */
143 } _G;
144
145 /* Resolved ifx structure. This structure stores information
146    about an iCode ifx that makes it easier to generate code.
147 */
148 typedef struct resolvedIfx {
149   symbol *lbl;     /* pointer to a label */
150   int condition;   /* true or false ifx */
151   int generated;   /* set true when the code associated with the ifx
152                     * is generated */
153 } resolvedIfx;
154
155 extern int pic16_ptrRegReq ;
156 extern int pic16_nRegs;
157 extern FILE *codeOutFile;
158 //static void saverbank (int, iCode *,bool);
159
160 static lineNode *lineHead = NULL;
161 static lineNode *lineCurr = NULL;
162
163 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
164 0xE0, 0xC0, 0x80, 0x00};
165 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
166 0x07, 0x03, 0x01, 0x00};
167
168 static  pBlock *pb;
169
170 /*-----------------------------------------------------------------*/
171 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
172 /*                 exponent of 2 is returned, otherwise -1 is      */
173 /*                 returned.                                       */
174 /* note that this is similar to the function `powof2' in SDCCsymt  */
175 /* if(n == 2^y)                                                    */
176 /*   return y;                                                     */
177 /* return -1;                                                      */
178 /*-----------------------------------------------------------------*/
179 static int my_powof2 (unsigned long num)
180 {
181   if(num) {
182     if( (num & (num-1)) == 0) {
183       int nshifts = -1;
184       while(num) {
185         num>>=1;
186         nshifts++;
187       }
188       return nshifts;
189     }
190   }
191
192   return -1;
193 }
194
195 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
196 {
197   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
198                        line_no,
199                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
200                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
201                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
202                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
203                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
204                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
205                        ((result) ? AOP_SIZE(result) : 0));
206 }
207
208 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
209 {
210
211   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
212                        line_no,
213                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
214                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
215                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
216                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
217                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
218                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
219
220 }
221
222 void pic16_emitpcomment (char *fmt, ...)
223 {
224     va_list ap;
225     char lb[INITIAL_INLINEASM];  
226     char *lbp = lb;
227
228     va_start(ap,fmt);   
229
230     lb[0] = ';';
231     vsprintf(lb+1,fmt,ap);
232
233     while (isspace(*lbp)) lbp++;
234
235     if (lbp && *lbp) 
236         lineCurr = (lineCurr ?
237                     connectLine(lineCurr,newLineNode(lb)) :
238                     (lineHead = newLineNode(lb)));
239     lineCurr->isInline = _G.inLine;
240     lineCurr->isDebug  = _G.debugLine;
241
242     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
243     va_end(ap);
244
245 //      fprintf(stderr, "%s\n", lb);
246 }
247
248 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
249 {
250     va_list ap;
251     char lb[INITIAL_INLINEASM];  
252     char *lbp = lb;
253
254     if(!pic16_debug_verbose)
255       return;
256
257     va_start(ap,fmt);   
258
259     if (inst && *inst) {
260         if (fmt && *fmt)
261             sprintf(lb,"%s\t",inst);
262         else
263             sprintf(lb,"%s",inst);
264         vsprintf(lb+(strlen(lb)),fmt,ap);
265     }  else
266         vsprintf(lb,fmt,ap);
267
268     while (isspace(*lbp)) lbp++;
269
270     if (lbp && *lbp) 
271         lineCurr = (lineCurr ?
272                     connectLine(lineCurr,newLineNode(lb)) :
273                     (lineHead = newLineNode(lb)));
274     lineCurr->isInline = _G.inLine;
275     lineCurr->isDebug  = _G.debugLine;
276
277     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
278     va_end(ap);
279
280 //      fprintf(stderr, "%s\n", lb);
281 }
282
283 void pic16_emitpLabel(int key)
284 {
285   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
286 }
287
288 void pic16_emitpLabelFORCE(int key)
289 {
290   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
291 }
292
293 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
294 {
295
296   if(pcop)
297     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
298   else
299     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
300 }
301
302 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
303 {
304   if(pcop)
305     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
306   else
307     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
308 }
309   
310 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
311 {
312
313   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
314
315 }
316
317
318 #if 1
319 #define pic16_emitcode  DEBUGpic16_emitcode
320 #else
321 /*-----------------------------------------------------------------*/
322 /* pic16_emitcode - writes the code into a file : for now it is simple    */
323 /*-----------------------------------------------------------------*/
324 void pic16_emitcode (char *inst,char *fmt, ...)
325 {
326     va_list ap;
327     char lb[INITIAL_INLINEASM];  
328     char *lbp = lb;
329
330     va_start(ap,fmt);   
331
332     if (inst && *inst) {
333         if (fmt && *fmt)
334             sprintf(lb,"%s\t",inst);
335         else
336             sprintf(lb,"%s",inst);
337         vsprintf(lb+(strlen(lb)),fmt,ap);
338     }  else
339         vsprintf(lb,fmt,ap);
340
341     while (isspace(*lbp)) lbp++;
342
343     if (lbp && *lbp) 
344         lineCurr = (lineCurr ?
345                     connectLine(lineCurr,newLineNode(lb)) :
346                     (lineHead = newLineNode(lb)));
347     lineCurr->isInline = _G.inLine;
348     lineCurr->isDebug  = _G.debugLine;
349
350 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
351
352 //    if(pic16_debug_verbose)
353 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
354
355     va_end(ap);
356 }
357 #endif
358
359
360 /*-----------------------------------------------------------------*/
361 /* pic16_emitDebuggerSymbol - associate the current code location  */
362 /*   with a debugger symbol                                        */
363 /*-----------------------------------------------------------------*/
364 void
365 pic16_emitDebuggerSymbol (char * debugSym)
366 {
367   _G.debugLine = 1;
368   pic16_emitcode (";", "%s ==.", debugSym);
369   _G.debugLine = 0;
370 }
371
372
373 /*-----------------------------------------------------------------*/
374 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
375 /*-----------------------------------------------------------------*/
376 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
377 {
378 //    bool r0iu = FALSE , r1iu = FALSE;
379 //    bool r0ou = FALSE , r1ou = FALSE;
380     bool fsr0iu = FALSE, fsr0ou;
381     bool fsr2iu = FALSE, fsr2ou;
382     
383     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
384
385     
386     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
387     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
388     
389     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
390     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
391
392     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
393         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
394         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
395     }
396
397     if(!fsr0iu && !fsr0ou) {
398         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
399         (*aopp)->type = AOP_FSR0;
400
401         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
402         
403       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
404     }
405
406 #if 0
407     /* no usage of FSR2 */
408     if(!fsr2iu && !fsr2ou) {
409         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
410         (*aopp)->type = AOP_FSR2;
411
412       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
413     }
414 #endif
415         
416     /* now we know they both have usage */
417     /* if fsr0 not used in this instruction */
418     if (!fsr0iu) {
419         if (!_G.fsr0Pushed) {
420                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
421                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
422                 _G.fsr0Pushed++;
423         }
424
425         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
426         (*aopp)->type = AOP_FSR0;
427
428 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
429
430       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
431     }
432         
433
434     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
435     assert( 0 );
436
437     return NULL;
438 #if 0
439     /* the logic: if r0 & r1 used in the instruction
440     then we are in trouble otherwise */
441
442     /* first check if r0 & r1 are used by this
443     instruction, in which case we are in trouble */
444     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
445         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
446     {
447         goto endOfWorld;      
448     }
449
450     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
451     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
452
453     /* if no usage of r0 then return it */
454     if (!r0iu && !r0ou) {
455         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
456         (*aopp)->type = AOP_R0; 
457         
458         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
459     }
460
461     /* if no usage of r1 then return it */
462     if (!r1iu && !r1ou) {
463         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
464         (*aopp)->type = AOP_R1;
465
466         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
467     }    
468
469     /* now we know they both have usage */
470     /* if r0 not used in this instruction */
471     if (!r0iu) {
472         /* push it if not already pushed */
473         if (!_G.r0Pushed) {
474           //pic16_emitcode ("push","%s",
475           //          pic16_regWithIdx(R0_IDX)->dname);
476             _G.r0Pushed++ ;
477         }
478         
479         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
480         (*aopp)->type = AOP_R0;
481
482         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
483     }
484
485     /* if r1 not used then */
486
487     if (!r1iu) {
488         /* push it if not already pushed */
489         if (!_G.r1Pushed) {
490           //pic16_emitcode ("push","%s",
491           //          pic16_regWithIdx(R1_IDX)->dname);
492             _G.r1Pushed++ ;
493         }
494         
495         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
496         (*aopp)->type = AOP_R1;
497         return pic16_regWithIdx(R1_IDX);
498     }
499
500 endOfWorld :
501     /* I said end of world but not quite end of world yet */
502     /* if this is a result then we can push it on the stack*/
503     if (result) {
504         (*aopp)->type = AOP_STK;    
505         return NULL;
506     }
507
508     /* other wise this is true end of the world */
509     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
510            "getFreePtr should never reach here");
511     exit(0);
512 #endif
513 }
514
515 /*-----------------------------------------------------------------*/
516 /* newAsmop - creates a new asmOp                                  */
517 /*-----------------------------------------------------------------*/
518 static asmop *newAsmop (short type)
519 {
520     asmop *aop;
521
522     aop = Safe_calloc(1,sizeof(asmop));
523     aop->type = type;
524     return aop;
525 }
526
527 static void genSetDPTR(int n)
528 {
529     if (!n)
530     {
531         pic16_emitcode(";", "Select standard DPTR");
532         pic16_emitcode("mov", "dps, #0x00");
533     }
534     else
535     {
536         pic16_emitcode(";", "Select alternate DPTR");
537         pic16_emitcode("mov", "dps, #0x01");
538     }
539 }
540
541 /*-----------------------------------------------------------------*/
542 /* resolveIfx - converts an iCode ifx into a form more useful for  */
543 /*              generating code                                    */
544 /*-----------------------------------------------------------------*/
545 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
546 {
547
548   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
549
550   if(!resIfx) 
551     return;
552
553
554   resIfx->condition = 1;    /* assume that the ifx is true */
555   resIfx->generated = 0;    /* indicate that the ifx has not been used */
556
557   if(!ifx) {
558     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
559
560 #if 1
561     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
562                         __FUNCTION__,__LINE__,resIfx->lbl->key);
563 #endif
564
565   } else {
566     if(IC_TRUE(ifx)) {
567       resIfx->lbl = IC_TRUE(ifx);
568     } else {
569       resIfx->lbl = IC_FALSE(ifx);
570       resIfx->condition = 0;
571     }
572
573 #if 1
574     if(IC_TRUE(ifx)) 
575       DEBUGpic16_emitcode("; ***","ifx true is non-null");
576     if(IC_FALSE(ifx)) 
577       DEBUGpic16_emitcode("; ***","ifx false is non-null");
578 #endif
579   }
580
581   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
582
583 }
584 #if 0
585 /*-----------------------------------------------------------------*/
586 /* pointerCode - returns the code for a pointer type               */
587 /*-----------------------------------------------------------------*/
588 static int pointerCode (sym_link *etype)
589 {
590
591     return PTR_TYPE(SPEC_OCLS(etype));
592
593 }
594 #endif
595
596 /*-----------------------------------------------------------------*/
597 /* aopForSym - for a true symbol                                   */
598 /*-----------------------------------------------------------------*/
599 static asmop *aopForSym (iCode *ic, operand *op, bool result)
600 {
601     symbol *sym=OP_SYMBOL(op);
602     asmop *aop;
603     memmap *space= SPEC_OCLS(sym->etype);
604
605     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
606
607     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
608     
609 //    sym = OP_SYMBOL(op);
610
611     /* if already has one */
612     if (sym->aop) {
613             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
614         return sym->aop;
615     }
616
617 #if 0
618     /* if symbol was initially placed onStack then we must re-place it
619      * to direct memory, since pic16 does not have a specific stack */
620     if(sym->onStack) {
621         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
622     }
623 #endif
624
625 #if 1
626     /* assign depending on the storage class */
627     /* if it is on the stack or indirectly addressable */
628     /* space we need to assign either r0 or r1 to it   */    
629     if (sym->onStack || sym->iaccess) {
630       pCodeOp *pcop[4];
631       int i;
632       
633         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
634                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
635         
636         /* acquire a temporary register -- it is saved in function */
637
638         sym->aop = aop = newAsmop(AOP_STA);
639         aop->aopu.stk.stk = sym->stack;
640         aop->size = getSize(sym->type);
641
642
643         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
644         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
645         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
646           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
647           
648           for(i=0;i<aop->size;i++)
649             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
650             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
651         } else
652           for(i=0;i<aop->size;i++) {
653             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
654             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
655           }
656
657
658 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
659
660 #if 1
661         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
662         
663         if(_G.accInUse) {
664                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
665         }
666         
667         for(i=0;i<aop->size;i++) {
668
669           /* initialise for stack access via frame pointer */
670           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
671
672           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
673                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
674         }
675         
676         if(_G.accInUse) {
677                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
678         }
679         
680         return (aop);
681 #endif
682
683 #if 0
684         /* now assign the address of the variable to 
685         the pointer register */
686         if (aop->type != AOP_STK) {
687
688             if (sym->onStack) {
689                     if ( _G.accInUse )
690                         pic16_emitcode("push","acc");
691
692                     pic16_emitcode("mov","a,_bp");
693                     pic16_emitcode("add","a,#0x%02x",
694                              ((sym->stack < 0) ?
695                               ((char)(sym->stack - _G.nRegsSaved )) :
696                               ((char)sym->stack)) & 0xff);
697                     pic16_emitcode("mov","%s,a",
698                              aop->aopu.aop_ptr->name);
699
700                     if ( _G.accInUse )
701                         pic16_emitcode("pop","acc");
702             } else
703                 pic16_emitcode("mov","%s,#%s",
704                          aop->aopu.aop_ptr->name,
705                          sym->rname);
706             aop->paged = space->paged;
707         } else
708             aop->aopu.aop_stk = sym->stack;
709         return aop;
710 #endif
711
712     }
713 #endif
714
715 #if 0
716     if (sym->onStack && options.stack10bit)
717     {
718         /* It's on the 10 bit stack, which is located in
719          * far data space.
720          */
721          
722       //DEBUGpic16_emitcode(";","%d",__LINE__);
723
724         if ( _G.accInUse )
725                 pic16_emitcode("push","acc");
726
727         pic16_emitcode("mov","a,_bp");
728         pic16_emitcode("add","a,#0x%02x",
729                  ((sym->stack < 0) ?
730                    ((char)(sym->stack - _G.nRegsSaved )) :
731                    ((char)sym->stack)) & 0xff);
732         
733         genSetDPTR(1);
734         pic16_emitcode ("mov","dpx1,#0x40");
735         pic16_emitcode ("mov","dph1,#0x00");
736         pic16_emitcode ("mov","dpl1, a");
737         genSetDPTR(0);
738         
739         if ( _G.accInUse )
740             pic16_emitcode("pop","acc");
741             
742         sym->aop = aop = newAsmop(AOP_DPTR2);
743         aop->size = getSize(sym->type); 
744         return aop;
745     }
746 #endif
747
748 #if 0
749     /* special case for a function */
750     if (IS_FUNC(sym->type)) {   
751         sym->aop = aop = newAsmop(AOP_PCODE);
752         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
753         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
754         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
755         PCOI(aop->aopu.pcop)->index = 0;
756         aop->size = FPTRSIZE; 
757         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
758         return aop;
759     }
760 #endif
761
762
763
764     //DEBUGpic16_emitcode(";","%d",__LINE__);
765     /* if in bit space */
766     if (IN_BITSPACE(space)) {
767         sym->aop = aop = newAsmop (AOP_CRY);
768         aop->aopu.aop_dir = sym->rname ;
769         aop->size = getSize(sym->type);
770         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
771         return aop;
772     }
773     /* if it is in direct space */
774     if (IN_DIRSPACE(space)) {
775         sym->aop = aop = newAsmop (AOP_DIR);
776         aop->aopu.aop_dir = sym->rname ;
777         aop->size = getSize(sym->type);
778         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
779         pic16_allocDirReg( IC_LEFT(ic) );
780         return aop;
781     }
782
783
784     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
785         sym->aop = aop = newAsmop (AOP_DIR);
786         aop->aopu.aop_dir = sym->rname ;
787         aop->size = getSize(sym->type);
788         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
789         pic16_allocDirReg( IC_LEFT(ic) );
790         return aop;
791     }
792
793
794     /* only remaining is far space */
795     sym->aop = aop = newAsmop(AOP_PCODE);
796
797 /* change the next if to 1 to revert to good old immediate code */
798         if(IN_CODESPACE(space)) {
799                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
800                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
801                 PCOI(aop->aopu.pcop)->index = 0;
802         } else {
803                 /* try to allocate via direct register */
804                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
805 //              aop->size = getSize( sym->type );
806         }
807
808         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
809                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
810
811 #if 0
812         if(!pic16_allocDirReg (IC_LEFT(ic)))
813                 return NULL;
814 #endif
815
816         if(IN_DIRSPACE( space ))
817                 aop->size = PTRSIZE;
818         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
819                 aop->size = FPTRSIZE;
820         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
821         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
822         else if(sym->onStack) {
823                 aop->size = PTRSIZE;
824         } else {
825                 assert( 0 );
826         }
827
828     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
829
830     /* if it is in code space */
831     if (IN_CODESPACE(space))
832         aop->code = 1;
833
834     return aop;     
835 }
836
837 /*-----------------------------------------------------------------*/
838 /* aopForRemat - rematerialzes an object                           */
839 /*-----------------------------------------------------------------*/
840 static asmop *aopForRemat (operand *op) // x symbol *sym)
841 {
842   symbol *sym = OP_SYMBOL(op);
843   operand *refop;
844   iCode *ic = NULL, *oldic;
845   asmop *aop = newAsmop(AOP_PCODE);
846   int val = 0;
847   int offset = 0;
848   int viaimmd=0;
849
850
851         ic = sym->rematiCode;
852
853         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
854         
855         if(IS_OP_POINTER(op)) {
856                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
857         }
858
859         for (;;) {
860                 oldic = ic;
861
862 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
863         
864                 if (ic->op == '+') {
865                         val += (int) operandLitValue(IC_RIGHT(ic));
866                 } else if (ic->op == '-') {
867                         val -= (int) operandLitValue(IC_RIGHT(ic));
868                 } else
869                         break;
870                 
871                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
872         }
873
874         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
875         refop = IC_LEFT(ic);
876
877         if(!op->isaddr)viaimmd++; else viaimmd=0;
878                 
879 /* set the following if to 1 to revert to good old immediate code */
880         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
881                 || viaimmd) {
882
883                 DEBUGpic16_emitcode(";", "%s:%d immediate", __FILE__, __LINE__);
884
885                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
886
887 #if 0
888                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
889 #else
890                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
891 #endif
892
893                 PCOI(aop->aopu.pcop)->index = val;
894         } else {
895                 DEBUGpic16_emitcode(";", "%s:%d dir", __FILE__, __LINE__);
896
897                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
898                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
899 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
900         }
901
902
903         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
904                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
905 #if 0
906                 val, IS_PTR_CONST(operandType(op)));
907 #else
908                 val, IS_CODEPTR(operandType(op)));
909 #endif
910
911 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
912
913         pic16_allocDirReg (IC_LEFT(ic));
914
915         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
916                 aop->code = 1;
917
918   return aop;        
919 }
920
921 #if 0
922 static int aopIdx (asmop *aop, int offset)
923 {
924   if(!aop)
925     return -1;
926
927   if(aop->type !=  AOP_REG)
928     return -2;
929         
930   return aop->aopu.aop_reg[offset]->rIdx;
931
932 }
933 #endif
934
935 /*-----------------------------------------------------------------*/
936 /* regsInCommon - two operands have some registers in common       */
937 /*-----------------------------------------------------------------*/
938 static bool regsInCommon (operand *op1, operand *op2)
939 {
940     symbol *sym1, *sym2;
941     int i;
942
943     /* if they have registers in common */
944     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
945         return FALSE ;
946
947     sym1 = OP_SYMBOL(op1);
948     sym2 = OP_SYMBOL(op2);
949
950     if (sym1->nRegs == 0 || sym2->nRegs == 0)
951         return FALSE ;
952
953     for (i = 0 ; i < sym1->nRegs ; i++) {
954         int j;
955         if (!sym1->regs[i])
956             continue ;
957
958         for (j = 0 ; j < sym2->nRegs ;j++ ) {
959             if (!sym2->regs[j])
960                 continue ;
961
962             if (sym2->regs[j] == sym1->regs[i])
963                 return TRUE ;
964         }
965     }
966
967     return FALSE ;
968 }
969
970 /*-----------------------------------------------------------------*/
971 /* operandsEqu - equivalent                                        */
972 /*-----------------------------------------------------------------*/
973 static bool operandsEqu ( operand *op1, operand *op2)
974 {
975     symbol *sym1, *sym2;
976
977     /* if they not symbols */
978     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
979         return FALSE;
980
981     sym1 = OP_SYMBOL(op1);
982     sym2 = OP_SYMBOL(op2);
983
984     /* if both are itemps & one is spilt
985        and the other is not then false */
986     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
987         sym1->isspilt != sym2->isspilt )
988         return FALSE ;
989
990     /* if they are the same */
991     if (sym1 == sym2)
992         return TRUE ;
993
994     if (sym1->rname[0] && sym2->rname[0]
995         && strcmp (sym1->rname, sym2->rname) == 0)
996         return TRUE;
997
998
999     /* if left is a tmp & right is not */
1000     if (IS_ITEMP(op1)  && 
1001         !IS_ITEMP(op2) &&
1002         sym1->isspilt  &&
1003         (sym1->usl.spillLoc == sym2))
1004         return TRUE;
1005
1006     if (IS_ITEMP(op2)  && 
1007         !IS_ITEMP(op1) &&
1008         sym2->isspilt  &&
1009         sym1->level > 0 &&
1010         (sym2->usl.spillLoc == sym1))
1011         return TRUE ;
1012
1013     return FALSE ;
1014 }
1015
1016 /*-----------------------------------------------------------------*/
1017 /* pic16_sameRegs - two asmops have the same registers                   */
1018 /*-----------------------------------------------------------------*/
1019 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1020 {
1021     int i;
1022
1023     if (aop1 == aop2)
1024         return TRUE ;
1025
1026     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1027                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1028
1029     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1030
1031     if (aop1->type != AOP_REG ||
1032         aop2->type != AOP_REG )
1033         return FALSE ;
1034
1035     if (aop1->size != aop2->size )
1036         return FALSE ;
1037
1038     for (i = 0 ; i < aop1->size ; i++ ) {
1039 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1040
1041 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1042         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1043             return FALSE ;
1044     }
1045
1046     return TRUE ;
1047 }
1048
1049 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1050 {
1051     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1052                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1053
1054     if(aop1 == aop2)return TRUE;
1055     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1056       
1057       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1058     
1059   return TRUE;
1060 }
1061
1062
1063 /*-----------------------------------------------------------------*/
1064 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1065 /*-----------------------------------------------------------------*/
1066 void pic16_aopOp (operand *op, iCode *ic, bool result)
1067 {
1068     asmop *aop;
1069     symbol *sym;
1070     int i;
1071
1072     if (!op)
1073         return ;
1074
1075 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1076
1077     /* if this a literal */
1078     if (IS_OP_LITERAL(op)) {
1079         op->aop = aop = newAsmop(AOP_LIT);
1080         aop->aopu.aop_lit = op->operand.valOperand;
1081         aop->size = getSize(operandType(op));
1082         return;
1083     }
1084
1085     {
1086       sym_link *type = operandType(op);
1087 #if 0
1088       if(IS_PTR_CONST(type))
1089 #else
1090       if(IS_CODEPTR(type))
1091 #endif
1092         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1093     }
1094
1095     /* if already has a asmop then continue */
1096     if (op->aop)
1097         return ;
1098
1099     /* if the underlying symbol has a aop */
1100     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1101       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1102         op->aop = OP_SYMBOL(op)->aop;
1103         return;
1104     }
1105
1106     /* if this is a true symbol */
1107     if (IS_TRUE_SYMOP(op)) {    
1108         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1109       op->aop = aopForSym(ic, op, result);
1110       return ;
1111     }
1112
1113     /* this is a temporary : this has
1114     only four choices :
1115     a) register
1116     b) spillocation
1117     c) rematerialize 
1118     d) conditional   
1119     e) can be a return use only */
1120
1121     sym = OP_SYMBOL(op);
1122
1123         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1124     /* if the type is a conditional */
1125     if (sym->regType == REG_CND) {
1126         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1127         aop->size = 0;
1128         return;
1129     }
1130
1131     /* if it is spilt then two situations
1132     a) is rematerialize 
1133     b) has a spill location */
1134     if (sym->isspilt || sym->nRegs == 0) {
1135
1136       DEBUGpic16_emitcode(";","%d",__LINE__);
1137         /* rematerialize it NOW */
1138         if (sym->remat) {
1139
1140             sym->aop = op->aop = aop = aopForRemat (op);
1141             aop->size = getSize(sym->type);
1142             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1143             return;
1144         }
1145
1146 #if 1
1147         if (sym->accuse) {
1148             int i;
1149             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1150             aop->size = getSize(sym->type);
1151             for ( i = 0 ; i < 1 ; i++ ) {
1152                 aop->aopu.aop_str[i] = accUse[i];
1153 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1154             }
1155             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1156             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1157             return;  
1158         }
1159 #endif
1160
1161 #if 1
1162         if (sym->ruonly ) {
1163           /*
1164           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1165           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1166           //pic16_allocDirReg (IC_LEFT(ic));
1167           aop->size = getSize(sym->type);
1168           */
1169
1170           unsigned i;
1171
1172           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1173           aop->size = getSize(sym->type);
1174           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1175             aop->aopu.aop_str[i] = fReturn[i];
1176
1177           DEBUGpic16_emitcode(";","%d",__LINE__);
1178           return;
1179         }
1180 #endif
1181         /* else spill location  */
1182         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1183             /* force a new aop if sizes differ */
1184             sym->usl.spillLoc->aop = NULL;
1185         }
1186
1187 #if 0
1188         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1189                             __FUNCTION__,__LINE__,
1190                             sym->usl.spillLoc->rname,
1191                             sym->rname, sym->usl.spillLoc->offset);
1192 #endif
1193
1194         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1195         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1196         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1197                                           getSize(sym->type), 
1198                                           sym->usl.spillLoc->offset, op);
1199         aop->size = getSize(sym->type);
1200
1201         return;
1202     }
1203
1204     {
1205       sym_link *type = operandType(op);
1206 #if 0
1207       if(IS_PTR_CONST(type)) 
1208 #else
1209       if(IS_CODEPTR(type)) 
1210 #endif
1211         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1212     }
1213
1214     /* must be in a register */
1215     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1216     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1217     aop->size = sym->nRegs;
1218     for ( i = 0 ; i < sym->nRegs ;i++)
1219         aop->aopu.aop_reg[i] = sym->regs[i];
1220 }
1221
1222 /*-----------------------------------------------------------------*/
1223 /* pic16_freeAsmop - free up the asmop given to an operand               */
1224 /*----------------------------------------------------------------*/
1225 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1226 {   
1227     asmop *aop ;
1228
1229     if (!op)
1230         aop = aaop;
1231     else 
1232         aop = op->aop;
1233
1234     if (!aop)
1235         return ;
1236
1237     if (aop->freed)
1238         goto dealloc; 
1239
1240     aop->freed = 1;
1241
1242     /* depending on the asmop type only three cases need work AOP_RO
1243        , AOP_R1 && AOP_STK */
1244 #if 1
1245     switch (aop->type) {
1246         case AOP_FSR0 :
1247             if (_G.fsr0Pushed ) {
1248                 if (pop) {
1249                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1250                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1251 //                    pic16_emitcode ("pop","ar0");
1252                     _G.fsr0Pushed--;
1253                 }
1254             }
1255             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1256             break;
1257
1258         case AOP_FSR2 :
1259             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1260             break;
1261
1262         case AOP_R0 :
1263             if (_G.r0Pushed ) {
1264                 if (pop) {
1265                     pic16_emitcode ("pop","ar0");     
1266                     _G.r0Pushed--;
1267                 }
1268             }
1269             bitVectUnSetBit(ic->rUsed,R0_IDX);
1270             break;
1271
1272         case AOP_R1 :
1273             if (_G.r1Pushed ) {
1274                 if (pop) {
1275                     pic16_emitcode ("pop","ar1");
1276                     _G.r1Pushed--;
1277                 }
1278             }
1279             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1280             break;
1281
1282         case AOP_STA:
1283           {
1284             int i;
1285
1286               /* we must store the result on stack */
1287               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1288                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1289                 for(i=0;i<aop->size;i++) {
1290                   /* initialise for stack access via frame pointer */
1291                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1292
1293                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1294                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1295                 }
1296         
1297                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1298               }
1299
1300               if(!_G.resDirect) {
1301                 for(i=0;i<aop->size;i++)
1302                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1303               }
1304               _G.resDirect = 0;
1305           }
1306           break;
1307 #if 0
1308         case AOP_STK :
1309         {
1310             int sz = aop->size;    
1311             int stk = aop->aopu.aop_stk + aop->size;
1312             bitVectUnSetBit(ic->rUsed,R0_IDX);
1313             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1314
1315             getFreePtr(ic,&aop,FALSE);
1316             
1317             if (options.stack10bit)
1318             {
1319                 /* I'm not sure what to do here yet... */
1320                 /* #STUB */
1321                 fprintf(stderr, 
1322                         "*** Warning: probably generating bad code for "
1323                         "10 bit stack mode.\n");
1324             }
1325             
1326             if (stk) {
1327                 pic16_emitcode ("mov","a,_bp");
1328                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1329                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1330             } else {
1331                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1332             }
1333
1334             while (sz--) {
1335                 pic16_emitcode("pop","acc");
1336                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1337                 if (!sz) break;
1338                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1339             }
1340             op->aop = aop;
1341             pic16_freeAsmop(op,NULL,ic,TRUE);
1342             if (_G.r0Pushed) {
1343                 pic16_emitcode("pop","ar0");
1344                 _G.r0Pushed--;
1345             }
1346
1347             if (_G.r1Pushed) {
1348                 pic16_emitcode("pop","ar1");
1349                 _G.r1Pushed--;
1350             }       
1351         }
1352 #endif
1353
1354     }
1355 #endif
1356
1357 dealloc:
1358     /* all other cases just dealloc */
1359     if (op ) {
1360         op->aop = NULL;
1361         if (IS_SYMOP(op)) {
1362             OP_SYMBOL(op)->aop = NULL;    
1363             /* if the symbol has a spill */
1364             if (SPIL_LOC(op))
1365                 SPIL_LOC(op)->aop = NULL;
1366         }
1367     }
1368 }
1369
1370 /*-----------------------------------------------------------------*/
1371 /* pic16_aopGet - for fetching value of the aop                          */
1372 /*-----------------------------------------------------------------*/
1373 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1374 {
1375     char *s = buffer ;
1376     char *rs;
1377
1378     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1379
1380     /* offset is greater than size then zero */
1381     if (offset > (aop->size - 1) &&
1382         aop->type != AOP_LIT)
1383         return zero;
1384
1385     /* depending on type */
1386     switch (aop->type) {
1387
1388     case AOP_FSR0:
1389     case AOP_FSR2:
1390       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1391       rs = Safe_calloc(1, strlen(s)+1);
1392       strcpy(rs, s);
1393       return (rs);
1394       
1395 #if 0
1396       /* if we need to increment it */
1397       while (offset > aop->coff)
1398         {
1399           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1400           aop->coff++;
1401         }
1402
1403       while (offset < aop->coff)
1404         {
1405           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1406           aop->coff--;
1407         }
1408       aop->coff = offset;
1409       if (aop->paged)
1410         {
1411           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1412           return (dname ? "acc" : "a");
1413         }
1414       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1415       rs = Safe_calloc (1, strlen (s) + 1);
1416       strcpy (rs, s);
1417       return rs;
1418 #endif
1419
1420         
1421     case AOP_IMMD:
1422         if (bit16) 
1423             sprintf (s,"%s",aop->aopu.aop_immd);
1424         else
1425             if (offset) 
1426                 sprintf(s,"(%s >> %d)",
1427                         aop->aopu.aop_immd,
1428                         offset*8);
1429             else
1430                 sprintf(s,"%s",
1431                         aop->aopu.aop_immd);
1432         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1433         rs = Safe_calloc(1,strlen(s)+1);
1434         strcpy(rs,s);   
1435         return rs;
1436         
1437     case AOP_DIR:
1438       if (offset) {
1439         sprintf(s,"(%s + %d)",
1440                 aop->aopu.aop_dir,
1441                 offset);
1442         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1443       } else
1444             sprintf(s,"%s",aop->aopu.aop_dir);
1445         rs = Safe_calloc(1,strlen(s)+1);
1446         strcpy(rs,s);   
1447         return rs;
1448         
1449     case AOP_REG:
1450       //if (dname) 
1451       //    return aop->aopu.aop_reg[offset]->dname;
1452       //else
1453             return aop->aopu.aop_reg[offset]->name;
1454         
1455     case AOP_CRY:
1456       //pic16_emitcode(";","%d",__LINE__);
1457       return aop->aopu.aop_dir;
1458         
1459     case AOP_ACC:
1460         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1461 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1462 //        assert( 0 );
1463 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1464         rs = Safe_strdup("WREG");
1465         return (rs);
1466
1467     case AOP_LIT:
1468         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1469         rs = Safe_calloc(1,strlen(s)+1);
1470         strcpy(rs,s);   
1471         return rs;
1472         
1473     case AOP_STR:
1474         aop->coff = offset ;
1475         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1476             dname)
1477             return "acc";
1478         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1479         
1480         return aop->aopu.aop_str[offset];
1481         
1482     case AOP_PCODE:
1483       {
1484         pCodeOp *pcop = aop->aopu.pcop;
1485         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1486         if(pcop->name) {
1487           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1488           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1489           sprintf(s,"%s", pcop->name);
1490         } else
1491           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1492
1493       }
1494       rs = Safe_calloc(1,strlen(s)+1);
1495       strcpy(rs,s);   
1496       return rs;
1497
1498     case AOP_STA:
1499         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1500         return (rs);
1501         
1502     case AOP_STK:
1503 //        pCodeOp *pcop = aop->aop
1504         break;
1505
1506     }
1507
1508     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1509     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1510            "aopget got unsupported aop->type");
1511     exit(0);
1512 }
1513
1514
1515
1516 /* lock has the following meaning: When allocating temporary registers
1517  * for stack variables storage, the value of the temporary register is
1518  * saved on stack. Its value is restored at the end. This procedure is
1519  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1520  * a possibility that before a call to pic16_aopOp, a temporary register
1521  * is allocated for a while and it is freed after some time, this will
1522  * mess the stack and values will not be restored properly. So use lock=1
1523  * to allocate temporary registers used internally by the programmer, and
1524  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1525  * to inform the compiler developer about a possible bug. This is an internal
1526  * feature for developing the compiler -- VR */
1527  
1528 int _TempReg_lock = 0;
1529 /*-----------------------------------------------------------------*/
1530 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1531 /*-----------------------------------------------------------------*/
1532 pCodeOp *pic16_popGetTempReg(int lock)
1533 {
1534   pCodeOp *pcop;
1535   symbol *cfunc;
1536
1537 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1538     if(_TempReg_lock) {
1539       werror(W_POSSBUG2, __FILE__, __LINE__);
1540     }
1541     
1542     _TempReg_lock += lock;
1543     
1544     cfunc = currFunc;
1545     currFunc = NULL;
1546
1547     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1548     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1549       PCOR(pcop)->r->wasUsed=1;
1550       PCOR(pcop)->r->isFree=0;
1551
1552       /* push value on stack */
1553       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1554     }
1555
1556     currFunc = cfunc;
1557
1558   return pcop;
1559 }
1560
1561 /*-----------------------------------------------------------------*/
1562 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1563 /*                            don't save if inside v               */
1564 /*-----------------------------------------------------------------*/
1565 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1566 {
1567   pCodeOp *pcop;
1568   symbol *cfunc;
1569
1570 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1571
1572     if(_TempReg_lock) {
1573       werror(W_POSSBUG2, __FILE__, __LINE__);
1574     }
1575
1576     _TempReg_lock += lock;
1577
1578     cfunc = currFunc;
1579     currFunc = NULL;
1580
1581     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1582     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1583       PCOR(pcop)->r->wasUsed=1;
1584       PCOR(pcop)->r->isFree=0;
1585
1586       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1587       /* push value on stack */
1588         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1589       }
1590     }
1591
1592     currFunc = cfunc;
1593
1594   return pcop;
1595 }
1596
1597
1598 /*-----------------------------------------------------------------*/
1599 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1600 /*-----------------------------------------------------------------*/
1601 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1602 {
1603   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1604
1605   _TempReg_lock -= lock;
1606
1607   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1608     PCOR(pcop)->r->isFree = 1;
1609     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1610   }
1611 }
1612 /*-----------------------------------------------------------------*/
1613 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1614 /*-----------------------------------------------------------------*/
1615 pCodeOp *pic16_popGetLabel(unsigned int key)
1616 {
1617
1618   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1619
1620   if(key>max_key)
1621     max_key = key;
1622
1623   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1624 }
1625
1626 /*-----------------------------------------------------------------*/
1627 /* pic16_popCopyReg - copy a pcode operator                              */
1628 /*-----------------------------------------------------------------*/
1629 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1630 {
1631   pCodeOpReg *pcor;
1632
1633   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1634   pcor->pcop.type = pc->pcop.type;
1635   if(pc->pcop.name) {
1636     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1637       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1638   } else
1639     pcor->pcop.name = NULL;
1640
1641   pcor->r = pc->r;
1642   pcor->rIdx = pc->rIdx;
1643   pcor->r->wasUsed=1;
1644
1645 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1646
1647   return PCOP(pcor);
1648 }
1649
1650 /*-----------------------------------------------------------------*/
1651 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1652 /*-----------------------------------------------------------------*/
1653 pCodeOp *pic16_popGetLit(int lit)
1654 {
1655   return pic16_newpCodeOpLit(lit);
1656 }
1657
1658 /*-----------------------------------------------------------------*/
1659 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1660 /*-----------------------------------------------------------------*/
1661 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1662 {
1663   return pic16_newpCodeOpLit2(lit, arg2);
1664 }
1665
1666
1667 /*-----------------------------------------------------------------*/
1668 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1669 /*-----------------------------------------------------------------*/
1670 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1671 {
1672   return pic16_newpCodeOpImmd(name, offset,index, 0);
1673 }
1674
1675
1676 /*-----------------------------------------------------------------*/
1677 /* pic16_popGet - asm operator to pcode operator conversion              */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popGetWithString(char *str)
1680 {
1681   pCodeOp *pcop;
1682
1683
1684   if(!str) {
1685     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1686     exit (1);
1687   }
1688
1689   pcop = pic16_newpCodeOp(str,PO_STR);
1690
1691   return pcop;
1692 }
1693
1694 /*-----------------------------------------------------------------*/
1695 /* pic16_popRegFromString -                                        */
1696 /*-----------------------------------------------------------------*/
1697 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1698 {
1699
1700   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1701   pcop->type = PO_DIR;
1702
1703   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1704   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1705
1706   if(!str)
1707     str = "BAD_STRING";
1708
1709   pcop->name = Safe_calloc(1,strlen(str)+1);
1710   strcpy(pcop->name,str);
1711
1712   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1713
1714   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1715
1716   /* make sure that register doesn't exist,
1717    * and operand isn't NULL
1718    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1719   if((PCOR(pcop)->r == NULL) 
1720     && (op)
1721     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1722 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1723 //              __FUNCTION__, __LINE__, str, size, offset);
1724
1725     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1726     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1727
1728   }
1729   PCOR(pcop)->instance = offset;
1730
1731   return pcop;
1732 }
1733
1734 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1735 {
1736   pCodeOp *pcop;
1737
1738 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1739
1740         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1741         PCOR(pcop)->rIdx = rIdx;
1742         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1743
1744         PCOR(pcop)->r->isFree = 0;
1745         PCOR(pcop)->r->wasUsed = 1;
1746
1747         pcop->type = PCOR(pcop)->r->pc_type;
1748
1749   return pcop;
1750 }
1751
1752 /*---------------------------------------------------------------------------------*/
1753 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1754 /*                 VR 030601                                                       */
1755 /*---------------------------------------------------------------------------------*/
1756 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1757 {
1758   pCodeOpReg2 *pcop2;
1759   pCodeOp *temp;
1760   
1761         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1762
1763         /* comment the following check, so errors to throw up */
1764 //      if(!pcop2)return NULL;
1765
1766         temp = pic16_popGet(aop_dst, offset);
1767         pcop2->pcop2 = temp;
1768         
1769   return PCOP(pcop2);
1770 }
1771
1772
1773
1774 /*--------------------------------------------------------------------------------.-*/
1775 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1776 /*                  VR 030601 , adapted by Hans Dorn                                */
1777 /*--------------------------------------------------------------------------------.-*/
1778 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1779 {
1780   pCodeOpReg2 *pcop2;
1781  
1782         pcop2 = (pCodeOpReg2 *)src;
1783         pcop2->pcop2 = dst;
1784         
1785         return PCOP(pcop2);
1786 }
1787
1788
1789
1790 /*---------------------------------------------------------------------------------*/
1791 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1792 /*                     movff instruction                                           */
1793 /*---------------------------------------------------------------------------------*/
1794 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1795 {
1796   pCodeOpReg2 *pcop2;
1797
1798         if(!noalloc) {
1799                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1800                 pcop2->pcop2 = pic16_popCopyReg(dst);
1801         } else {
1802                 /* the pCodeOp may be already allocated */
1803                 pcop2 = (pCodeOpReg2 *)(src);
1804                 pcop2->pcop2 = (pCodeOp *)(dst);
1805         }
1806
1807   return PCOP(pcop2);
1808 }
1809
1810
1811 /*-----------------------------------------------------------------*/
1812 /* pic16_popGet - asm operator to pcode operator conversion              */
1813 /*-----------------------------------------------------------------*/
1814 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1815 {
1816   //char *s = buffer ;
1817   char *rs;
1818   pCodeOp *pcop;
1819
1820     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1821     /* offset is greater than
1822     size then zero */
1823
1824 //    if (offset > (aop->size - 1) &&
1825 //        aop->type != AOP_LIT)
1826 //      return NULL;  //zero;
1827
1828     /* depending on type */
1829     switch (aop->type) {
1830         
1831     case AOP_R0:
1832     case AOP_R1:
1833     case AOP_DPTR:
1834     case AOP_DPTR2:
1835         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1836         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1837         assert( 0 );
1838         return NULL;
1839
1840
1841     case AOP_FSR0:
1842     case AOP_FSR2:
1843       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1844       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1845       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1846       PCOR(pcop)->r->wasUsed = 1;
1847       PCOR(pcop)->r->isFree = 0;
1848       
1849       PCOR(pcop)->instance = offset;
1850       pcop->type = PCOR(pcop)->r->pc_type;
1851       return (pcop);
1852
1853     case AOP_IMMD:
1854       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1855       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1856
1857     case AOP_STA:
1858       /* pCodeOp is already allocated from aopForSym */
1859         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1860         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1861           
1862       return (pcop);
1863       
1864     case AOP_ACC:
1865       {
1866         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1867
1868         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1869
1870         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1871         
1872         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1873         PCOR(pcop)->rIdx = rIdx;
1874         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1875         PCOR(pcop)->r->wasUsed=1;
1876         PCOR(pcop)->r->isFree=0;
1877
1878         PCOR(pcop)->instance = offset;
1879         pcop->type = PCOR(pcop)->r->pc_type;
1880 //      rs = aop->aopu.aop_reg[offset]->name;
1881 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1882         return pcop;
1883
1884
1885 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1886 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1887
1888 //      assert( 0 );
1889       }
1890         
1891     case AOP_DIR:
1892       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1893       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1894         
1895     case AOP_REG:
1896       {
1897         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1898
1899         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1900         
1901         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1902 //      pcop->type = PO_GPR_REGISTER;
1903         PCOR(pcop)->rIdx = rIdx;
1904         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1905         PCOR(pcop)->r->wasUsed=1;
1906         PCOR(pcop)->r->isFree=0;
1907
1908         PCOR(pcop)->instance = offset;
1909         pcop->type = PCOR(pcop)->r->pc_type;
1910         rs = aop->aopu.aop_reg[offset]->name;
1911         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1912         return pcop;
1913       }
1914
1915     case AOP_CRY:
1916         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1917
1918       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1919       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1920       //if(PCOR(pcop)->r == NULL)
1921       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1922       return pcop;
1923         
1924     case AOP_LIT:
1925         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1926       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1927
1928     case AOP_STR:
1929       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1930       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1931
1932       /*
1933       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1934       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1935       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1936       pcop->type = PCOR(pcop)->r->pc_type;
1937       pcop->name = PCOR(pcop)->r->name;
1938
1939       return pcop;
1940       */
1941
1942     case AOP_PCODE:
1943       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1944                           __LINE__, 
1945                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1946       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1947 #if 1
1948         switch( aop->aopu.pcop->type ) {
1949                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1950                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1951                 default:
1952                         assert( 0 );    /* should never reach here */;
1953         }
1954 #else
1955       PCOI(pcop)->offset = offset;
1956 #endif
1957       return pcop;
1958     }
1959
1960     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1961            "pic16_popGet got unsupported aop->type");
1962     exit(0);
1963 }
1964 /*-----------------------------------------------------------------*/
1965 /* pic16_aopPut - puts a string for a aop                                */
1966 /*-----------------------------------------------------------------*/
1967 void pic16_aopPut (asmop *aop, char *s, int offset)
1968 {
1969     char *d = buffer ;
1970     symbol *lbl ;
1971
1972     return;
1973
1974     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1975
1976     if (aop->size && offset > ( aop->size - 1)) {
1977         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1978                "pic16_aopPut got offset > aop->size");
1979         exit(0);
1980     }
1981
1982     /* will assign value to value */
1983     /* depending on where it is ofcourse */
1984     switch (aop->type) {
1985     case AOP_DIR:
1986       if (offset) {
1987         sprintf(d,"(%s + %d)",
1988                 aop->aopu.aop_dir,offset);
1989         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1990
1991       } else
1992             sprintf(d,"%s",aop->aopu.aop_dir);
1993         
1994         if (strcmp(d,s)) {
1995           DEBUGpic16_emitcode(";","%d",__LINE__);
1996           if(strcmp(s,"W"))
1997             pic16_emitcode("movf","%s,w",s);
1998           pic16_emitcode("movwf","%s",d);
1999
2000           if(strcmp(s,"W")) {
2001             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2002             if(offset >= aop->size) {
2003               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2004               break;
2005             } else
2006               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2007           }
2008
2009           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2010
2011
2012         }
2013         break;
2014         
2015     case AOP_REG:
2016       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2017         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2018           /*
2019             if (*s == '@'           ||
2020                 strcmp(s,"r0") == 0 ||
2021                 strcmp(s,"r1") == 0 ||
2022                 strcmp(s,"r2") == 0 ||
2023                 strcmp(s,"r3") == 0 ||
2024                 strcmp(s,"r4") == 0 ||
2025                 strcmp(s,"r5") == 0 ||
2026                 strcmp(s,"r6") == 0 || 
2027                 strcmp(s,"r7") == 0 )
2028                 pic16_emitcode("mov","%s,%s  ; %d",
2029                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2030             else
2031           */
2032
2033           if(strcmp(s,"W")==0 )
2034             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2035
2036           pic16_emitcode("movwf","%s",
2037                    aop->aopu.aop_reg[offset]->name);
2038
2039           if(strcmp(s,zero)==0) {
2040             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2041
2042           } else if(strcmp(s,"W")==0) {
2043             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2044             pcop->type = PO_GPR_REGISTER;
2045
2046             PCOR(pcop)->rIdx = -1;
2047             PCOR(pcop)->r = NULL;
2048
2049             DEBUGpic16_emitcode(";","%d",__LINE__);
2050             pcop->name = Safe_strdup(s);
2051             pic16_emitpcode(POC_MOVFW,pcop);
2052             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2053           } else if(strcmp(s,one)==0) {
2054             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2055             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2056           } else {
2057             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2058           }
2059         }
2060         break;
2061         
2062     case AOP_DPTR:
2063     case AOP_DPTR2:
2064     
2065     if (aop->type == AOP_DPTR2)
2066     {
2067         genSetDPTR(1);
2068     }
2069     
2070         if (aop->code) {
2071             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2072                    "pic16_aopPut writting to code space");
2073             exit(0);
2074         }
2075         
2076         while (offset > aop->coff) {
2077             aop->coff++;
2078             pic16_emitcode ("inc","dptr");
2079         }
2080         
2081         while (offset < aop->coff) {
2082             aop->coff-- ;
2083             pic16_emitcode("lcall","__decdptr");
2084         }
2085         
2086         aop->coff = offset;
2087         
2088         /* if not in accumulater */
2089         MOVA(s);        
2090         
2091         pic16_emitcode ("movx","@dptr,a");
2092         
2093     if (aop->type == AOP_DPTR2)
2094     {
2095         genSetDPTR(0);
2096     }
2097         break;
2098         
2099     case AOP_R0:
2100     case AOP_R1:
2101         while (offset > aop->coff) {
2102             aop->coff++;
2103             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2104         }
2105         while (offset < aop->coff) {
2106             aop->coff-- ;
2107             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2108         }
2109         aop->coff = offset;
2110         
2111         if (aop->paged) {
2112             MOVA(s);           
2113             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2114             
2115         } else
2116             if (*s == '@') {
2117                 MOVA(s);
2118                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2119             } else
2120                 if (strcmp(s,"r0") == 0 ||
2121                     strcmp(s,"r1") == 0 ||
2122                     strcmp(s,"r2") == 0 ||
2123                     strcmp(s,"r3") == 0 ||
2124                     strcmp(s,"r4") == 0 ||
2125                     strcmp(s,"r5") == 0 ||
2126                     strcmp(s,"r6") == 0 || 
2127                     strcmp(s,"r7") == 0 ) {
2128                     char buffer[10];
2129                     sprintf(buffer,"a%s",s);
2130                     pic16_emitcode("mov","@%s,%s",
2131                              aop->aopu.aop_ptr->name,buffer);
2132                 } else
2133                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2134         
2135         break;
2136         
2137     case AOP_STK:
2138         if (strcmp(s,"a") == 0)
2139             pic16_emitcode("push","acc");
2140         else
2141             pic16_emitcode("push","%s",s);
2142         
2143         break;
2144         
2145     case AOP_CRY:
2146         /* if bit variable */
2147         if (!aop->aopu.aop_dir) {
2148             pic16_emitcode("clr","a");
2149             pic16_emitcode("rlc","a");
2150         } else {
2151             if (s == zero) 
2152                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2153             else
2154                 if (s == one)
2155                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2156                 else
2157                     if (!strcmp(s,"c"))
2158                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2159                     else {
2160                         lbl = newiTempLabel(NULL);
2161                         
2162                         if (strcmp(s,"a")) {
2163                             MOVA(s);
2164                         }
2165                         pic16_emitcode("clr","c");
2166                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2167                         pic16_emitcode("cpl","c");
2168                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2169                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2170                     }
2171         }
2172         break;
2173         
2174     case AOP_STR:
2175         aop->coff = offset;
2176         if (strcmp(aop->aopu.aop_str[offset],s))
2177             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2178         break;
2179         
2180     case AOP_ACC:
2181         aop->coff = offset;
2182         if (!offset && (strcmp(s,"acc") == 0))
2183             break;
2184         
2185         if (strcmp(aop->aopu.aop_str[offset],s))
2186             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2187         break;
2188
2189     default :
2190         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2191 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2192 //             "pic16_aopPut got unsupported aop->type");
2193 //      exit(0);    
2194     }    
2195
2196 }
2197
2198 /*-----------------------------------------------------------------*/
2199 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2200 /*-----------------------------------------------------------------*/
2201 static void mov2w (asmop *aop, int offset)
2202 {
2203   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2204
2205   if(is_LitAOp(aop))
2206     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2207   else
2208     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2209 }
2210
2211 static void mov2f(asmop *dst, asmop *src, int offset)
2212 {
2213   if(is_LitAOp(src)) {
2214     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2215     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2216   } else {
2217     if(pic16_sameRegsOfs(src, dst, offset))return;
2218     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2219                       pic16_popGet(dst, offset)));
2220   }
2221 }
2222
2223 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2224 {
2225   if(is_LitAOp(src)) {
2226     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2227     pic16_emitpcode(POC_MOVWF, dst);
2228   } else {
2229     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2230   }
2231 }
2232
2233
2234 /* push pcop into stack */
2235 void pic16_pushpCodeOp(pCodeOp *pcop)
2236 {
2237 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2238         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2239 }
2240
2241 /* pop pcop from stack */
2242 void pic16_poppCodeOp(pCodeOp *pcop)
2243 {
2244         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2245 }
2246
2247
2248 /*-----------------------------------------------------------------*/
2249 /* pushw - pushes wreg to stack                                    */
2250 /*-----------------------------------------------------------------*/
2251 void pushw(void)
2252 {
2253         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2254         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2255 }
2256
2257                 
2258 /*-----------------------------------------------------------------*/
2259 /* pushaop - pushes aop to stack                                   */
2260 /*-----------------------------------------------------------------*/
2261 void pushaop(asmop *aop, int offset)
2262 {
2263         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2264         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2265 }
2266
2267 /*-----------------------------------------------------------------*/
2268 /* popaop - pops aop from stack                                    */
2269 /*-----------------------------------------------------------------*/
2270 void popaop(asmop *aop, int offset)
2271 {
2272         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2273         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2274 }
2275
2276 void popaopidx(asmop *aop, int offset, int index)
2277 {
2278   int ofs=1;
2279
2280         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2281
2282         if(STACK_MODEL_LARGE)ofs++;
2283
2284         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2285         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2286 }
2287
2288 /*-----------------------------------------------------------------*/
2289 /* reAdjustPreg - points a register back to where it should        */
2290 /*-----------------------------------------------------------------*/
2291 static void reAdjustPreg (asmop *aop)
2292 {
2293     int size ;
2294
2295     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2296     aop->coff = 0;
2297     if ((size = aop->size) <= 1)
2298         return ;
2299     size-- ;
2300     switch (aop->type) {
2301         case AOP_R0 :
2302         case AOP_R1 :
2303             while (size--)
2304                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2305             break;          
2306         case AOP_DPTR :
2307         case AOP_DPTR2:
2308             if (aop->type == AOP_DPTR2)
2309             {
2310                 genSetDPTR(1);
2311             } 
2312             while (size--)
2313             {
2314                 pic16_emitcode("lcall","__decdptr");
2315             }
2316                 
2317             if (aop->type == AOP_DPTR2)
2318             {
2319                 genSetDPTR(0);
2320             }                
2321             break;  
2322
2323     }   
2324
2325 }
2326
2327
2328 #if 0
2329 /*-----------------------------------------------------------------*/
2330 /* opIsGptr: returns non-zero if the passed operand is             */   
2331 /* a generic pointer type.                                         */
2332 /*-----------------------------------------------------------------*/ 
2333 static int opIsGptr(operand *op)
2334 {
2335     sym_link *type = operandType(op);
2336     
2337     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2338     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2339     {
2340         return 1;
2341     }
2342     return 0;        
2343 }
2344 #endif
2345
2346 /*-----------------------------------------------------------------*/
2347 /* pic16_getDataSize - get the operand data size                         */
2348 /*-----------------------------------------------------------------*/
2349 int pic16_getDataSize(operand *op)
2350 {
2351     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2352
2353
2354     return AOP_SIZE(op);
2355
2356     // tsd- in the pic port, the genptr size is 1, so this code here
2357     // fails. ( in the 8051 port, the size was 4).
2358 #if 0
2359     int size;
2360     size = AOP_SIZE(op);
2361     if (size == GPTRSIZE)
2362     {
2363         sym_link *type = operandType(op);
2364         if (IS_GENPTR(type))
2365         {
2366             /* generic pointer; arithmetic operations
2367              * should ignore the high byte (pointer type).
2368              */
2369             size--;
2370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2371         }
2372     }
2373     return size;
2374 #endif
2375 }
2376
2377 /*-----------------------------------------------------------------*/
2378 /* pic16_outAcc - output Acc                                             */
2379 /*-----------------------------------------------------------------*/
2380 void pic16_outAcc(operand *result)
2381 {
2382   int size,offset;
2383   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2384   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2385
2386
2387   size = pic16_getDataSize(result);
2388   if(size){
2389     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2390     size--;
2391     offset = 1;
2392     /* unsigned or positive */
2393     while(size--)
2394       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2395   }
2396
2397 }
2398
2399 /*-----------------------------------------------------------------*/
2400 /* pic16_outBitC - output a bit C                                  */
2401 /*                 Move to result the value of Carry flag -- VR    */
2402 /*-----------------------------------------------------------------*/
2403 void pic16_outBitC(operand *result)
2404 {
2405   int i;
2406
2407     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2408     /* if the result is bit */
2409     if (AOP_TYPE(result) == AOP_CRY) {
2410         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2411         pic16_aopPut(AOP(result),"c",0);
2412     } else {
2413
2414         i = AOP_SIZE(result);
2415         while(i--) {
2416                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2417         }
2418         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2419         
2420 /*
2421         pic16_emitcode("clr","a  ; %d", __LINE__);
2422         pic16_emitcode("rlc","a");
2423         pic16_outAcc(result);
2424 */
2425     }
2426 }
2427
2428 /*-----------------------------------------------------------------*/
2429 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2430 /*-----------------------------------------------------------------*/
2431 void pic16_toBoolean(operand *oper)
2432 {
2433     int size = AOP_SIZE(oper) - 1;
2434     int offset = 1;
2435
2436     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2437
2438     if ( AOP_TYPE(oper) != AOP_ACC) {
2439       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2440     }
2441     while (size--) {
2442       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2443     }
2444 }
2445
2446
2447 #if !defined(GEN_Not)
2448 /*-----------------------------------------------------------------*/
2449 /* genNot - generate code for ! operation                          */
2450 /*-----------------------------------------------------------------*/
2451 static void pic16_genNot (iCode *ic)
2452 {
2453   symbol *tlbl;
2454   int size;
2455
2456   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2457   /* assign asmOps to operand & result */
2458   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2459   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2460
2461   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2462   /* if in bit space then a special case */
2463   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2464     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2465       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2466       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2467     } else {
2468       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2469       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2470       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2471     }
2472     goto release;
2473   }
2474
2475   size = AOP_SIZE(IC_LEFT(ic));
2476   if(size == 1) {
2477     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2478     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2479     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2480     goto release;
2481   }
2482   pic16_toBoolean(IC_LEFT(ic));
2483
2484   tlbl = newiTempLabel(NULL);
2485   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2486   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2487   pic16_outBitC(IC_RESULT(ic));
2488
2489  release:    
2490   /* release the aops */
2491   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2492   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2493 }
2494 #endif
2495
2496
2497 #if !defined(GEN_Cpl)
2498 /*-----------------------------------------------------------------*/
2499 /* genCpl - generate code for complement                           */
2500 /*-----------------------------------------------------------------*/
2501 static void pic16_genCpl (iCode *ic)
2502 {
2503     int offset = 0;
2504     int size ;
2505
2506
2507     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2508     /* assign asmOps to operand & result */
2509     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2510     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2511
2512     /* if both are in bit space then 
2513     a special case */
2514     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2515         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2516
2517         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2518         pic16_emitcode("cpl","c"); 
2519         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2520         goto release; 
2521     } 
2522
2523     size = AOP_SIZE(IC_RESULT(ic));
2524     while (size--) {
2525 /*
2526         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2527         MOVA(l);       
2528         pic16_emitcode("cpl","a");
2529         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2530 */
2531         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2532               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2533         } else {
2534                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2535                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2536         }
2537         offset++;
2538
2539     }
2540
2541
2542 release:
2543     /* release the aops */
2544     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2545     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2546 }
2547 #endif
2548
2549 /*-----------------------------------------------------------------*/
2550 /* genUminusFloat - unary minus for floating points                */
2551 /*-----------------------------------------------------------------*/
2552 static void genUminusFloat(operand *op,operand *result)
2553 {
2554     int size ,offset =0 ;
2555     char *l;
2556
2557     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2558     /* for this we just need to flip the 
2559     first it then copy the rest in place */
2560     size = AOP_SIZE(op) - 1;
2561     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2562
2563     MOVA(l);    
2564
2565     pic16_emitcode("cpl","acc.7");
2566     pic16_aopPut(AOP(result),"a",3);    
2567
2568     while(size--) {
2569         pic16_aopPut(AOP(result),
2570                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2571                offset);
2572         offset++;
2573     }          
2574 }
2575
2576 /*-----------------------------------------------------------------*/
2577 /* genUminus - unary minus code generation                         */
2578 /*-----------------------------------------------------------------*/
2579 static void genUminus (iCode *ic)
2580 {
2581   int size, i;
2582   sym_link *optype, *rtype;
2583
2584         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2585         
2586         /* assign asmops */
2587         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2588         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2589
2590         /* if both in bit space then special case */
2591         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2592                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2593
2594                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2595                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2596                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2597                 
2598                 goto release; 
2599         } 
2600
2601         optype = operandType(IC_LEFT(ic));
2602         rtype = operandType(IC_RESULT(ic));
2603
2604         /* if float then do float stuff */
2605         if (IS_FLOAT(optype)) {
2606                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2607                 goto release;
2608         }
2609
2610         /* otherwise subtract from zero by taking the 2's complement */
2611         size = AOP_SIZE(IC_LEFT(ic));
2612
2613         for(i=0; i<size; i++) {
2614                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2615                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2616                 else {
2617                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2618                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2619                 }
2620         }
2621
2622         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2623         for(i=1; i<size; i++) {
2624                 emitSKPNZ;
2625                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2626         }
2627
2628 release:
2629         /* release the aops */
2630         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2631         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2632 }
2633
2634 #if 0
2635 /*-----------------------------------------------------------------*/
2636 /* saveRegisters - will look for a call and save the registers     */
2637 /*-----------------------------------------------------------------*/
2638 static void saveRegisters(iCode *lic) 
2639 {
2640     int i;
2641     iCode *ic;
2642     bitVect *rsave;
2643     sym_link *dtype;
2644
2645     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2646     /* look for call */
2647     for (ic = lic ; ic ; ic = ic->next) 
2648         if (ic->op == CALL || ic->op == PCALL)
2649             break;
2650
2651     if (!ic) {
2652         fprintf(stderr,"found parameter push with no function call\n");
2653         return ;
2654     }
2655
2656     /* if the registers have been saved already then
2657     do nothing */
2658     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2659         return ;
2660
2661     /* find the registers in use at this time 
2662     and push them away to safety */
2663     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2664                           ic->rUsed);
2665
2666     ic->regsSaved = 1;
2667     if (options.useXstack) {
2668         if (bitVectBitValue(rsave,R0_IDX))
2669             pic16_emitcode("mov","b,r0");
2670         pic16_emitcode("mov","r0,%s",spname);
2671         for (i = 0 ; i < pic16_nRegs ; i++) {
2672             if (bitVectBitValue(rsave,i)) {
2673                 if (i == R0_IDX)
2674                     pic16_emitcode("mov","a,b");
2675                 else
2676                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2677                 pic16_emitcode("movx","@r0,a");
2678                 pic16_emitcode("inc","r0");
2679             }
2680         }
2681         pic16_emitcode("mov","%s,r0",spname);
2682         if (bitVectBitValue(rsave,R0_IDX))
2683             pic16_emitcode("mov","r0,b");           
2684     }// else
2685     //for (i = 0 ; i < pic16_nRegs ; i++) {
2686     //    if (bitVectBitValue(rsave,i))
2687     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2688     //}
2689
2690     dtype = operandType(IC_LEFT(ic));
2691     if (currFunc && dtype && 
2692         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2693         IFFUNC_ISISR(currFunc->type) &&
2694         !ic->bankSaved) 
2695
2696         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2697
2698 }
2699 /*-----------------------------------------------------------------*/
2700 /* unsaveRegisters - pop the pushed registers                      */
2701 /*-----------------------------------------------------------------*/
2702 static void unsaveRegisters (iCode *ic)
2703 {
2704     int i;
2705     bitVect *rsave;
2706
2707     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2708     /* find the registers in use at this time 
2709     and push them away to safety */
2710     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2711                           ic->rUsed);
2712     
2713     if (options.useXstack) {
2714         pic16_emitcode("mov","r0,%s",spname);   
2715         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2716             if (bitVectBitValue(rsave,i)) {
2717                 pic16_emitcode("dec","r0");
2718                 pic16_emitcode("movx","a,@r0");
2719                 if (i == R0_IDX)
2720                     pic16_emitcode("mov","b,a");
2721                 else
2722                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2723             }       
2724
2725         }
2726         pic16_emitcode("mov","%s,r0",spname);
2727         if (bitVectBitValue(rsave,R0_IDX))
2728             pic16_emitcode("mov","r0,b");
2729     } //else
2730     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2731     //    if (bitVectBitValue(rsave,i))
2732     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2733     //}
2734
2735 }  
2736 #endif
2737
2738 #if 0  // patch 14
2739 /*-----------------------------------------------------------------*/
2740 /* pushSide -                                                      */
2741 /*-----------------------------------------------------------------*/
2742 static void pushSide(operand * oper, int size)
2743 {
2744         int offset = 0;
2745     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2746         while (size--) {
2747                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2748                 if (AOP_TYPE(oper) != AOP_REG &&
2749                     AOP_TYPE(oper) != AOP_DIR &&
2750                     strcmp(l,"a") ) {
2751                         pic16_emitcode("mov","a,%s",l);
2752                         pic16_emitcode("push","acc");
2753                 } else
2754                         pic16_emitcode("push","%s",l);
2755         }
2756 }
2757 #endif // patch 14
2758
2759 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2760 {
2761   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2762     pic16_emitpcode(POC_MOVFW, src);
2763     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2764   } else {
2765     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2766         src, pic16_popGet(AOP(op), offset)));
2767   }
2768 }
2769
2770
2771 /*-----------------------------------------------------------------*/
2772 /* assignResultValue - assign results to oper, rescall==1 is       */
2773 /*                     called from genCall() or genPCall()         */
2774 /*-----------------------------------------------------------------*/
2775 static void assignResultValue(operand * oper, int rescall)
2776 {
2777   int size = AOP_SIZE(oper);
2778   int offset=0;
2779   
2780     DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2781     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2782
2783     if(rescall) {
2784       /* assign result from a call/pcall function() */
2785                 
2786       /* function results are stored in a special order,
2787        * see top of file with Function return policy, or manual */
2788
2789       if(size <= 4) {
2790         /* 8-bits, result in WREG */
2791         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2792                         
2793         if(size>1) {
2794           /* 16-bits, result in PRODL:WREG */
2795           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2796         }
2797                         
2798         if(size>2) {
2799           /* 24-bits, result in PRODH:PRODL:WREG */
2800           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2801         }
2802                         
2803         if(size>3) {
2804           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2805           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2806         }
2807       
2808       } else {
2809         /* >32-bits, result on stack, and FSR0 points to beginning.
2810          * Fix stack when done */
2811         /* FIXME FIXME */
2812         while (size--) {
2813 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2814 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2815                 
2816           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2817           GpsuedoStkPtr++;
2818         }
2819                         
2820         /* fix stack */
2821         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2822         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2823         if(STACK_MODEL_LARGE) {
2824           emitSKPNC;
2825           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2826         }
2827       }                 
2828     } else {
2829       int areg = 0;             /* matching argument register */
2830       
2831       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2832
2833
2834       /* its called from genReceive (probably) -- VR */
2835       if(!GpsuedoStkPtr && _G.useWreg) {
2836 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2837
2838         /* The last byte in the assignment is in W */
2839         if(areg <= GpsuedoStkPtr) {
2840           size--;
2841           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2842           offset++;
2843         }
2844       }
2845 //      GpsuedoStkPtr++;
2846       _G.stack_lat = AOP_SIZE(oper)-1;
2847
2848       while (size) {
2849         size--;
2850         GpsuedoStkPtr++;
2851         popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2852         offset++;
2853       }
2854     }
2855 }
2856
2857
2858 /*-----------------------------------------------------------------*/
2859 /* genIpush - generate code for pushing this gets a little complex */
2860 /*-----------------------------------------------------------------*/
2861 static void genIpush (iCode *ic)
2862 {
2863 //  int size, offset=0;
2864
2865   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2866
2867
2868   if(ic->parmPush) {
2869     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2870
2871     /* send to stack as normal */
2872     addSet(&_G.sendSet,ic);
2873 //    addSetHead(&_G.sendSet,ic);
2874     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2875   }
2876
2877         
2878 #if 0
2879     int size, offset = 0 ;
2880     char *l;
2881
2882
2883     /* if this is not a parm push : ie. it is spill push 
2884     and spill push is always done on the local stack */
2885     if (!ic->parmPush) {
2886
2887         /* and the item is spilt then do nothing */
2888         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2889             return ;
2890
2891         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2892         size = AOP_SIZE(IC_LEFT(ic));
2893         /* push it on the stack */
2894         while(size--) {
2895             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2896             if (*l == '#') {
2897                 MOVA(l);
2898                 l = "acc";
2899             }
2900             pic16_emitcode("push","%s",l);
2901         }
2902         return ;        
2903     }
2904
2905     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2906 #endif
2907 }
2908
2909 /*-----------------------------------------------------------------*/
2910 /* genIpop - recover the registers: can happen only for spilling   */
2911 /*-----------------------------------------------------------------*/
2912 static void genIpop (iCode *ic)
2913 {
2914   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2915 #if 0
2916     int size,offset ;
2917
2918
2919     /* if the temp was not pushed then */
2920     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2921         return ;
2922
2923     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2924     size = AOP_SIZE(IC_LEFT(ic));
2925     offset = (size-1);
2926     while (size--) 
2927         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2928                                    FALSE,TRUE));
2929
2930     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2931 #endif
2932 }
2933
2934 #if 0
2935 /*-----------------------------------------------------------------*/
2936 /* unsaverbank - restores the resgister bank from stack            */
2937 /*-----------------------------------------------------------------*/
2938 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2939 {
2940   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2941 #if 0
2942     int i;
2943     asmop *aop ;
2944     regs *r = NULL;
2945
2946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2947     if (popPsw) {
2948         if (options.useXstack) {
2949             aop = newAsmop(0);
2950             r = getFreePtr(ic,&aop,FALSE);
2951             
2952             
2953             pic16_emitcode("mov","%s,_spx",r->name);
2954             pic16_emitcode("movx","a,@%s",r->name);
2955             pic16_emitcode("mov","psw,a");
2956             pic16_emitcode("dec","%s",r->name);
2957             
2958         }else
2959             pic16_emitcode ("pop","psw");
2960     }
2961
2962     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2963         if (options.useXstack) {       
2964             pic16_emitcode("movx","a,@%s",r->name);
2965             //pic16_emitcode("mov","(%s+%d),a",
2966             //       regspic16[i].base,8*bank+regspic16[i].offset);
2967             pic16_emitcode("dec","%s",r->name);
2968
2969         } else 
2970           pic16_emitcode("pop",""); //"(%s+%d)",
2971         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2972     }
2973
2974     if (options.useXstack) {
2975
2976         pic16_emitcode("mov","_spx,%s",r->name);
2977         pic16_freeAsmop(NULL,aop,ic,TRUE);
2978
2979     }
2980 #endif 
2981 }
2982
2983 /*-----------------------------------------------------------------*/
2984 /* saverbank - saves an entire register bank on the stack          */
2985 /*-----------------------------------------------------------------*/
2986 static void saverbank (int bank, iCode *ic, bool pushPsw)
2987 {
2988   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2989 #if 0
2990     int i;
2991     asmop *aop ;
2992     regs *r = NULL;
2993
2994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2995     if (options.useXstack) {
2996
2997         aop = newAsmop(0);
2998         r = getFreePtr(ic,&aop,FALSE);  
2999         pic16_emitcode("mov","%s,_spx",r->name);
3000
3001     }
3002
3003     for (i = 0 ; i < pic16_nRegs ;i++) {
3004         if (options.useXstack) {
3005             pic16_emitcode("inc","%s",r->name);
3006             //pic16_emitcode("mov","a,(%s+%d)",
3007             //         regspic16[i].base,8*bank+regspic16[i].offset);
3008             pic16_emitcode("movx","@%s,a",r->name);           
3009         } else 
3010           pic16_emitcode("push","");// "(%s+%d)",
3011                      //regspic16[i].base,8*bank+regspic16[i].offset);
3012     }
3013     
3014     if (pushPsw) {
3015         if (options.useXstack) {
3016             pic16_emitcode("mov","a,psw");
3017             pic16_emitcode("movx","@%s,a",r->name);     
3018             pic16_emitcode("inc","%s",r->name);
3019             pic16_emitcode("mov","_spx,%s",r->name);       
3020             pic16_freeAsmop (NULL,aop,ic,TRUE);
3021             
3022         } else
3023             pic16_emitcode("push","psw");
3024         
3025         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3026     }
3027     ic->bankSaved = 1;
3028 #endif
3029 }
3030 #endif  /* 0 */
3031
3032
3033 /*-----------------------------------------------------------------*/
3034 /* genCall - generates a call statement                            */
3035 /*-----------------------------------------------------------------*/
3036 static void genCall (iCode *ic)
3037 {
3038   sym_link *ftype;   
3039   int stackParms=0;
3040   int use_wreg=0;
3041   char *fname;
3042   
3043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3044
3045     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3046     /* if caller saves & we have not saved then */
3047 //    if (!ic->regsSaved)
3048 //      saveRegisters(ic);
3049
3050         /* initialise stackParms for IPUSH pushes */
3051 //      stackParms = psuedoStkPtr;
3052 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3053     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3054
3055 #if 0
3056     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3057 #endif
3058
3059     /* if send set is not empty the assign */
3060     if (_G.sendSet) {
3061       iCode *sic;
3062       int psuedoStkPtr=-1; 
3063       int firstTimeThruLoop = 1;
3064
3065
3066 #if 1
3067         /* reverse sendSet if function is not reentrant */
3068         if(!IFFUNC_ISREENT(ftype))
3069           _G.sendSet = reverseSet(_G.sendSet);
3070 #endif
3071
3072         /* First figure how many parameters are getting passed */
3073
3074 /*      do we really need to know this ? -- VR 
3075         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3076           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3077           psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3078           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3079         }
3080 */
3081
3082
3083 //        stackParms = psuedoStkPtr;
3084         stackParms = 0;
3085         use_wreg = 0;
3086         
3087         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3088           int size, offset = 0;
3089
3090             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3091             size = AOP_SIZE(IC_LEFT(sic));
3092
3093             stackParms += size;
3094
3095             while (size--) {
3096               DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3097                     pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3098               DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3099
3100               if(!firstTimeThruLoop) {
3101                 /* If this is not the first time we've been through the loop
3102                  * then we need to save the parameter in a temporary
3103                  * register. The last byte of the last parameter is
3104                  * passed in W. */
3105
3106                 pushw();
3107 //                --psuedoStkPtr;               // sanity check
3108               }
3109                 
3110               firstTimeThruLoop=0;
3111
3112               mov2w (AOP(IC_LEFT(sic)), size);
3113
3114               offset++;
3115             }
3116             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3117           }
3118
3119           /* save last parameter to stack if functions has varargs */
3120           if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype))pushw();
3121           else use_wreg = 1;            /* last parameter in WREG */
3122           
3123           _G.stackRegSet = _G.sendSet;
3124           _G.sendSet = NULL;
3125     }
3126
3127     /* make the call */
3128     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3129
3130     GpsuedoStkPtr=0;
3131     /* if we need to assign a result value */
3132     if ((IS_ITEMP(IC_RESULT(ic))
3133           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3134               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3135         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3136
3137       _G.accInUse++;
3138       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3139       _G.accInUse--;
3140
3141       assignResultValue(IC_RESULT(ic), 1);
3142
3143       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3144                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3145                 
3146       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3147     }
3148
3149     if(!stackParms && ic->parmBytes) {
3150       stackParms = ic->parmBytes;
3151     }
3152       
3153     stackParms -= use_wreg;
3154       
3155     if(stackParms>0) {
3156       if(stackParms == 1) {
3157         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3158       } else {
3159         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3160         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3161       }
3162       if(STACK_MODEL_LARGE) {
3163         emitSKPNC;
3164         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3165       }
3166     }
3167
3168 #if 0
3169     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3170 #endif
3171
3172     /* adjust the stack for parameters if required */
3173 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3174
3175 #if 0
3176       /* if register bank was saved then pop them */
3177       if (ic->bankSaved)
3178         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3179
3180       /* if we hade saved some registers then unsave them */
3181       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3182         unsaveRegisters (ic);
3183 #endif
3184 }
3185
3186
3187
3188 /*-----------------------------------------------------------------*/
3189 /* genPcall - generates a call by pointer statement                */
3190 /*            new version, created from genCall - HJD              */
3191 /*-----------------------------------------------------------------*/
3192 static void genPcall (iCode *ic)
3193 {
3194   sym_link *ftype;
3195   int stackParms=0;
3196   symbol *retlbl = newiTempLabel(NULL);
3197   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3198   int use_wreg=0;
3199   
3200     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3201
3202     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3203     
3204     /* if send set is not empty the assign */
3205     if (_G.sendSet) {
3206       iCode *sic;
3207       int psuedoStkPtr=-1; 
3208       int firstTimeThruLoop = 1;
3209
3210       /* For the Pic port, there is no data stack.
3211        * So parameters passed to functions are stored
3212        * in registers. (The pCode optimizer will get
3213        * rid of most of these :). */
3214
3215
3216 #if 1
3217       /* reverse sendSet if function is not reentrant */
3218       if(!IFFUNC_ISREENT(ftype))
3219         _G.sendSet = reverseSet(_G.sendSet);
3220 #endif
3221
3222       /* First figure how many parameters are getting passed */
3223 #if 0
3224       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3225         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3226         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3227         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3228       }
3229 #endif
3230
3231 //      stackParms = psuedoStkPtr;
3232       stackParms = 0;
3233
3234       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3235         int size, offset = 0;
3236
3237           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3238           size = AOP_SIZE(IC_LEFT(sic));
3239           stackParms += size;
3240
3241           while (size--) {
3242             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3243             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3244             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3245
3246             if(!firstTimeThruLoop) {
3247               /* If this is not the first time we've been through the loop
3248                * then we need to save the parameter in a temporary
3249                * register. The last byte of the last parameter is
3250                * passed in W. */
3251
3252               pushw();
3253               --psuedoStkPtr;           // sanity check
3254             }
3255                         
3256             firstTimeThruLoop=0;
3257
3258             mov2w (AOP(IC_LEFT(sic)), size);
3259
3260             offset++;
3261           }
3262
3263
3264           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3265       }
3266
3267       if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype))pushw();
3268       else use_wreg = 1;                /* last parameter in WREG */
3269
3270       _G.stackRegSet = _G.sendSet;
3271       _G.sendSet = NULL;
3272     }
3273
3274     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3275
3276     // push return address
3277     // push $ on return stack, then replace with retlbl
3278
3279     pic16_emitpcodeNULLop(POC_PUSH);
3280
3281     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3282     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3283     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3284     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3285     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3286     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3287
3288     /* make the call by writing the pointer into pc */
3289     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3290     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3291
3292     // note: MOVFF to PCL not allowed
3293     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3294     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3295
3296
3297     /* return address is here: (X) */
3298     pic16_emitpLabelFORCE(retlbl->key);
3299
3300     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3301
3302     GpsuedoStkPtr=0;
3303     /* if we need assign a result value */
3304     if ((IS_ITEMP(IC_RESULT(ic))
3305           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3306               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3307         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3308
3309       _G.accInUse++;
3310       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3311       _G.accInUse--;
3312
3313       assignResultValue(IC_RESULT(ic), 1);
3314
3315       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3316               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3317                 
3318       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3319     }
3320
3321     stackParms -= use_wreg;
3322     
3323     if(stackParms>0) {
3324       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3325       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3326       if(STACK_MODEL_LARGE) {
3327         /* this implies that stackParms < 256 !!! -- VR */
3328         emitSKPNC;
3329         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3330       }
3331     }
3332 }
3333
3334 /*-----------------------------------------------------------------*/
3335 /* resultRemat - result  is rematerializable                       */
3336 /*-----------------------------------------------------------------*/
3337 static int resultRemat (iCode *ic)
3338 {
3339   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3340   if (SKIP_IC(ic) || ic->op == IFX)
3341     return 0;
3342
3343   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3344     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3345     if (sym->remat && !POINTER_SET(ic)) 
3346       return 1;
3347   }
3348
3349   return 0;
3350 }
3351
3352 #if defined(__BORLANDC__) || defined(_MSC_VER)
3353 #define STRCASECMP stricmp
3354 #else
3355 #define STRCASECMP strcasecmp
3356 #endif
3357
3358 #if 0
3359 /*-----------------------------------------------------------------*/
3360 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3361 /*-----------------------------------------------------------------*/
3362 static bool inExcludeList(char *s)
3363 {
3364   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3365     int i =0;
3366     
3367     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3368     if (options.excludeRegs[i] &&
3369     STRCASECMP(options.excludeRegs[i],"none") == 0)
3370         return FALSE ;
3371
3372     for ( i = 0 ; options.excludeRegs[i]; i++) {
3373         if (options.excludeRegs[i] &&
3374         STRCASECMP(s,options.excludeRegs[i]) == 0)
3375             return TRUE;
3376     }
3377     return FALSE ;
3378 }
3379 #endif
3380
3381 /*-----------------------------------------------------------------*/
3382 /* genFunction - generated code for function entry                 */
3383 /*-----------------------------------------------------------------*/
3384 static void genFunction (iCode *ic)
3385 {
3386   symbol *sym;
3387   sym_link *ftype;
3388   
3389     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3390
3391     pic16_labelOffset += (max_key+4);
3392     max_key=0;
3393     GpsuedoStkPtr=0;
3394     _G.nRegsSaved = 0;
3395         
3396     ftype = operandType(IC_LEFT(ic));
3397     sym = OP_SYMBOL(IC_LEFT(ic));
3398
3399     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3400       /* create an absolute section at the interrupt vector:
3401        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3402       symbol *asym;
3403       char asymname[128];
3404       pBlock *apb;
3405
3406         {
3407           int i, found=-1;
3408
3409             sym = OP_SYMBOL( IC_LEFT(ic));
3410             for(i=0;i<=2;i++) {
3411               if(interrupts[i]->name
3412                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3413                   found = i;
3414                   break;
3415               }
3416             }
3417                         
3418             if(found == -1) {
3419               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3420                             __FILE__, __LINE__, sym->name);
3421               assert( 0 );
3422             }
3423             _G.interruptvector = found;
3424         }
3425
3426         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3427         asym = newSymbol(asymname, 0);
3428
3429         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3430         pic16_addpBlock( apb );
3431
3432         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3433         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3434         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3435                 
3436         /* mark the end of this tiny function */
3437         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3438
3439         {
3440           absSym *abSym;
3441
3442             abSym = Safe_calloc(1, sizeof(absSym));
3443             strcpy(abSym->name, asymname);
3444
3445             switch( _G.interruptvector ) {
3446               case 0: abSym->address = 0x000000; break;
3447               case 1: abSym->address = 0x000008; break;
3448               case 2: abSym->address = 0x000018; break;
3449             }
3450
3451             /* relocate interrupt vectors if needed */
3452             abSym->address += pic16_options.ivt_loc;
3453
3454             addSet(&absSymSet, abSym);
3455         }
3456     }
3457
3458     /* create the function header */
3459     pic16_emitcode(";","-----------------------------------------");
3460     pic16_emitcode(";"," function %s",sym->name);
3461     pic16_emitcode(";","-----------------------------------------");
3462
3463     pic16_emitcode("","%s:",sym->rname);
3464     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3465
3466
3467     {
3468       absSym *ab;
3469
3470         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3471           if(!strcmp(ab->name, sym->rname)) {
3472             pic16_pBlockConvert2Absolute(pb);
3473             break;
3474           }
3475         }
3476     }
3477
3478
3479     if(IFFUNC_ISNAKED(ftype)) {
3480       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3481       return;
3482     }
3483         
3484     /* if critical function then turn interrupts off */
3485     if (IFFUNC_ISCRITICAL(ftype)) {
3486       //pic16_emitcode("clr","ea");
3487     }
3488
3489     _G.fregsUsed = sym->regsUsed;
3490
3491     /* if this is an interrupt service routine then
3492      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3493     if (IFFUNC_ISISR(sym->type)) {
3494         _G.usefastretfie = 1;   /* use shadow registers by default */
3495         
3496         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3497         if(!(_G.interruptvector == 1)) {
3498           /* do not save WREG,STATUS,BSR for high priority interrupts
3499            * because they are stored in the hardware shadow registers already */
3500           _G.usefastretfie = 0;
3501           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3502           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3503           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3504         }
3505
3506         /* these should really be optimized somehow, because not all
3507          * interrupt handlers modify them */
3508         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3509         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3510         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3511         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3512         
3513 //        pic16_pBlockConvert2ISR(pb);
3514                 
3515     }
3516
3517     /* emit code to setup stack frame if user enabled,
3518      * and function is not main() */
3519          
3520     //fprintf(stderr, "function name: %s\n", sym->name);
3521     if(strcmp(sym->name, "main")) {
3522       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3523         /* setup the stack frame */
3524         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3525         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3526         if(STACK_MODEL_LARGE)
3527           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3528       }
3529     }
3530
3531     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3532           && sym->stack) {
3533
3534       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3535
3536       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3537       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3538       emitSKPNC;
3539       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3540     }
3541           
3542     if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3543       _G.useWreg = 0;
3544     else _G.useWreg = 1;
3545
3546     /* if callee-save to be used for this function
3547      * then save the registers being used in this function */
3548 //    if (IFFUNC_CALLEESAVES(sym->type))
3549     {
3550       int i;
3551
3552         /* if any registers used */
3553         if (sym->regsUsed) {
3554           /* save the registers used */
3555           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3556           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3557           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3558             if (bitVectBitValue(sym->regsUsed,i)) {
3559               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3560               _G.nRegsSaved++;
3561
3562               if(!pic16_regWithIdx(i)->wasUsed) {
3563                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3564                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3565                 pic16_regWithIdx(i)->wasUsed = 1;
3566               }
3567             }
3568           }
3569           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3570         }
3571     }
3572         
3573     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3574 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3575 }
3576
3577 /*-----------------------------------------------------------------*/
3578 /* genEndFunction - generates epilogue for functions               */
3579 /*-----------------------------------------------------------------*/
3580 static void genEndFunction (iCode *ic)
3581 {
3582   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3583
3584     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3585
3586     if(IFFUNC_ISNAKED(sym->type)) {
3587       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3588       return;
3589     }
3590
3591     _G.stack_lat = 0;
3592
3593     /* add code for ISCRITICAL */
3594     if(IFFUNC_ISCRITICAL(sym->type)) {
3595       /* if critical function, turn on interrupts */
3596       
3597       /* TODO: add code here -- VR */
3598     }
3599     
3600     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3601           && sym->stack) {
3602       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3603       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3604       emitSKPNC;
3605       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3606     }
3607
3608     /* now we need to restore the registers */
3609     /* if any registers used */
3610     if (sym->regsUsed) {
3611       int i;
3612
3613         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3614         /* restore registers used */
3615         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3616         for ( i = sym->regsUsed->size; i >= 0; i--) {
3617           if (bitVectBitValue(sym->regsUsed,i)) {
3618             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3619             _G.nRegsSaved--;
3620           }
3621         }
3622         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3623
3624     }
3625
3626     if(strcmp(sym->name, "main")) {
3627       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3628         /* restore stack frame */
3629         if(STACK_MODEL_LARGE)
3630           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3631         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3632       }
3633     }
3634
3635     _G.useWreg = 0;
3636
3637     if (IFFUNC_ISISR(sym->type)) {
3638       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3639       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3640       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3641       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3642
3643       if(!(_G.interruptvector == 1)) {
3644         /* do not restore interrupt vector for WREG,STATUS,BSR
3645          * for high priority interrupt, see genFunction */
3646         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3647         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3648         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3649       }
3650       _G.interruptvector = 0;           /* sanity check */
3651
3652
3653       /* if debug then send end of function */
3654 /*      if (options.debug && currFunc)  */
3655       if (currFunc) {
3656         debugFile->writeEndFunction (currFunc, ic, 1);
3657       }
3658         
3659       if(_G.usefastretfie)
3660         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3661       else
3662         pic16_emitpcodeNULLop(POC_RETFIE);
3663
3664       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3665       
3666       _G.usefastretfie = 0;
3667       return;
3668     }
3669
3670     if (IFFUNC_ISCRITICAL(sym->type)) {
3671       pic16_emitcode("setb","ea");
3672     }
3673
3674     /* if debug then send end of function */
3675     if (currFunc) {
3676       debugFile->writeEndFunction (currFunc, ic, 1);
3677     }
3678
3679     /* insert code to restore stack frame, if user enabled it
3680      * and function is not main() */
3681          
3682
3683     pic16_emitpcodeNULLop(POC_RETURN);
3684
3685     /* Mark the end of a function */
3686     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3687 }
3688
3689
3690 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3691 {
3692   if(is_LitOp(op)) {
3693     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3694     if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3695   } else {
3696     if(dest->type == PO_WREG && (offset == 0)) {
3697       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3698       return;
3699     }
3700     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3701   }
3702 }
3703
3704 /*-----------------------------------------------------------------*/
3705 /* genRet - generate code for return statement                     */
3706 /*-----------------------------------------------------------------*/
3707 static void genRet (iCode *ic)
3708 {
3709   int size;
3710   operand *left;
3711
3712         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3713         /* if we have no return value then
3714          * just generate the "ret" */
3715         
3716         if (!IC_LEFT(ic)) 
3717                 goto jumpret;       
3718     
3719         /* we have something to return then
3720          * move the return value into place */
3721         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3722         size = AOP_SIZE(IC_LEFT(ic));
3723
3724         if(size <= 4) {
3725                 if(size>3) {
3726                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3727 //                      pic16_emitpcode(POC_MOVFF,
3728 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3729                 }
3730                 if(size>2) {
3731                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3732 //                      pic16_emitpcode(POC_MOVFF,
3733 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3734                 }
3735                 if(size>1) {
3736                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3737 //                      pic16_emitpcode(POC_MOVFF,
3738 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3739                 }
3740
3741 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3742
3743                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3744 //              pic16_emitpcode(POC_MOVFF,
3745 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3746
3747         } else {
3748                 /* >32-bits, setup stack and FSR0 */
3749                 while (size--) {
3750 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3751 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3752
3753                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3754
3755 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3756                         GpsuedoStkPtr++;
3757                 }
3758                         
3759                 /* setup FSR0 */
3760                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3761                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3762
3763                 if(STACK_MODEL_LARGE) {
3764                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3765                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3766                 } else {
3767                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3768                 }
3769         }
3770                                 
3771 #if 0
3772         /* old code, left here for reference -- VR */    
3773         while (size--) {
3774           char *l ;
3775
3776                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3777                         /* #NOCHANGE */
3778                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3779                         pic16_emitpcomment("push %s",l);
3780                         pushed++;
3781                 } else {
3782                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3783                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3784                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3785                         
3786                         if (strcmp(fReturn[offset],l)) {
3787                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3788                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3789                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3790                                 } else {
3791                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3792                                 }
3793                                 
3794                                 if(size) {
3795                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3796                                 }
3797                                 offset++;
3798                         }
3799                 }
3800         }    
3801
3802         if (pushed) {
3803                 while(pushed) {
3804                         pushed--;
3805                         if (strcmp(fReturn[pushed],"a"))
3806                                 pic16_emitcode("pop",fReturn[pushed]);
3807                         else
3808                                 pic16_emitcode("pop","acc");
3809                 }
3810         }
3811 #endif
3812
3813
3814         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3815     
3816 jumpret:
3817         /* generate a jump to the return label
3818          * if the next is not the return statement */
3819         if (!(ic->next && ic->next->op == LABEL
3820                 && IC_LABEL(ic->next) == returnLabel)) {
3821         
3822                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3823                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3824         }
3825 }
3826
3827 /*-----------------------------------------------------------------*/
3828 /* genLabel - generates a label                                    */
3829 /*-----------------------------------------------------------------*/
3830 static void genLabel (iCode *ic)
3831 {
3832
3833
3834     /* special case never generate */
3835     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3836     if (IC_LABEL(ic) == entryLabel)
3837         return ;
3838
3839     pic16_emitpLabel(IC_LABEL(ic)->key);
3840     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3841 }
3842
3843 /*-----------------------------------------------------------------*/
3844 /* genGoto - generates a goto                                      */
3845 /*-----------------------------------------------------------------*/
3846 //tsd
3847 static void genGoto (iCode *ic)
3848 {
3849   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3850   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3851 }
3852
3853
3854 /*-----------------------------------------------------------------*/
3855 /* genMultbits :- multiplication of bits                           */
3856 /*-----------------------------------------------------------------*/
3857 static void genMultbits (operand *left, 
3858                          operand *right, 
3859                          operand *result)
3860 {
3861   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3862
3863   if(!pic16_sameRegs(AOP(result),AOP(right)))
3864     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3865
3866   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3867   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3868   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3869
3870 }
3871
3872
3873 /*-----------------------------------------------------------------*/
3874 /* genMultOneByte : 8 bit multiplication & division                */
3875 /*-----------------------------------------------------------------*/
3876 static void genMultOneByte (operand *left,
3877                             operand *right,
3878                             operand *result)
3879 {
3880
3881   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3882   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3883   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3884
3885   /* (if two literals, the value is computed before) */
3886   /* if one literal, literal on the right */
3887   if (AOP_TYPE(left) == AOP_LIT){
3888     operand *t = right;
3889     right = left;
3890     left = t;
3891   }
3892
3893         /* size is already checked in genMult == 1 */
3894 //      size = AOP_SIZE(result);
3895
3896         if (AOP_TYPE(right) == AOP_LIT){
3897                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3898                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3899                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3900                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3901         } else {
3902                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3903                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3904                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3905                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3906         }
3907         
3908         pic16_genMult8X8_8 (left, right,result);
3909 }
3910
3911 /*-----------------------------------------------------------------*/
3912 /* genMultOneWord : 16 bit multiplication                          */
3913 /*-----------------------------------------------------------------*/
3914 static void genMultOneWord (operand *left,
3915                             operand *right,
3916                             operand *result)
3917 {
3918
3919         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3920         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3921         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3922
3923         /* (if two literals, the value is computed before)
3924          * if one literal, literal on the right */
3925         if (AOP_TYPE(left) == AOP_LIT){
3926           operand *t = right;
3927                 right = left;
3928                 left = t;
3929         }
3930
3931         /* size is checked already == 2 */
3932 //      size = AOP_SIZE(result);
3933
3934         if (AOP_TYPE(right) == AOP_LIT) {
3935                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3936                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3937                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3938                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3939         } else {
3940                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3941                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3942                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3943                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3944         }
3945         
3946         pic16_genMult16X16_16(left, right,result);
3947 }
3948
3949 /*-----------------------------------------------------------------*/
3950 /* genMultOneLong : 32 bit multiplication                          */
3951 /*-----------------------------------------------------------------*/
3952 static void genMultOneLong (operand *left,
3953                             operand *right,
3954                             operand *result)
3955 {
3956
3957         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3958         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3959         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3960
3961         /* (if two literals, the value is computed before)
3962          * if one literal, literal on the right */
3963         if (AOP_TYPE(left) == AOP_LIT){
3964           operand *t = right;
3965                 right = left;
3966                 left = t;
3967         }
3968
3969         /* size is checked already == 4 */
3970 //      size = AOP_SIZE(result);
3971
3972         if (AOP_TYPE(right) == AOP_LIT) {
3973                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3974                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3975                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3976                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3977         } else {
3978                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3979                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3980                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3981                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3982         }
3983         
3984         pic16_genMult32X32_32(left, right,result);
3985 }
3986
3987
3988
3989 /*-----------------------------------------------------------------*/
3990 /* genMult - generates code for multiplication                     */
3991 /*-----------------------------------------------------------------*/
3992 static void genMult (iCode *ic)
3993 {
3994   operand *left = IC_LEFT(ic);
3995   operand *right = IC_RIGHT(ic);
3996   operand *result= IC_RESULT(ic);   
3997
3998         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3999         /* assign the amsops */
4000         pic16_aopOp (left,ic,FALSE);
4001         pic16_aopOp (right,ic,FALSE);
4002         pic16_aopOp (result,ic,TRUE);
4003
4004         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4005
4006         /* special cases first *
4007         * both are bits */
4008         if (AOP_TYPE(left) == AOP_CRY
4009                 && AOP_TYPE(right)== AOP_CRY) {
4010                 genMultbits(left,right,result);
4011           goto release ;
4012         }
4013
4014         /* if both are of size == 1 */
4015         if(AOP_SIZE(left) == 1
4016                 && AOP_SIZE(right) == 1) {
4017                 genMultOneByte(left,right,result);
4018           goto release ;
4019         }
4020
4021         /* if both are of size == 2 */
4022         if(AOP_SIZE(left) == 2
4023                 && AOP_SIZE(right) == 2) {
4024                 genMultOneWord(left, right, result);
4025           goto release;
4026         }
4027         
4028         /* if both are of size == 4 */
4029         if(AOP_SIZE(left) == 4
4030                 && AOP_SIZE(right) == 4) {
4031                 genMultOneLong(left, right, result);
4032           goto release;
4033         }
4034         
4035         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4036
4037
4038         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4039         /* should have been converted to function call */
4040         assert(0) ;
4041
4042 release :
4043         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4044         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4045         pic16_freeAsmop(result,NULL,ic,TRUE); 
4046 }
4047
4048 /*-----------------------------------------------------------------*/
4049 /* genDivbits :- division of bits                                  */
4050 /*-----------------------------------------------------------------*/
4051 static void genDivbits (operand *left, 
4052                         operand *right, 
4053                         operand *result)
4054 {
4055
4056     char *l;
4057
4058     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4059     /* the result must be bit */    
4060     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4061     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4062
4063     MOVA(l);    
4064
4065     pic16_emitcode("div","ab");
4066     pic16_emitcode("rrc","a");
4067     pic16_aopPut(AOP(result),"c",0);
4068 }
4069
4070 /*-----------------------------------------------------------------*/
4071 /* genDivOneByte : 8 bit division                                  */
4072 /*-----------------------------------------------------------------*/
4073 static void genDivOneByte (operand *left,
4074                            operand *right,
4075                            operand *result)
4076 {
4077     sym_link *opetype = operandType(result);
4078     char *l ;
4079     symbol *lbl ;
4080     int size,offset;
4081
4082         /* result = divident / divisor
4083          * - divident may be a register or a literal,
4084          * - divisor may be a register or a literal,
4085          * so there are 3 cases (literal / literal is optimized
4086          * by the front-end) to handle.
4087          * In addition we must handle signed and unsigned, which
4088          * result in 6 final different cases -- VR */
4089
4090     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4091     size = AOP_SIZE(result) - 1;
4092     offset = 1;
4093     /* signed or unsigned */
4094     if (SPEC_USIGN(opetype)) {
4095       pCodeOp *pct1,    /* count */
4096                 *pct2,  /* reste */
4097                 *pct3;  /* temp */
4098       symbol *label1, *label2, *label3;;
4099
4100
4101         /* unsigned is easy */
4102
4103         pct1 = pic16_popGetTempReg(1);
4104         pct2 = pic16_popGetTempReg(1);
4105         pct3 = pic16_popGetTempReg(1);
4106         
4107         label1 = newiTempLabel(NULL);
4108         label2 = newiTempLabel(NULL);
4109         label3 = newiTempLabel(NULL);
4110
4111         /* the following algorithm is extracted from divuint.c */
4112
4113         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4114         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4115         
4116         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4117
4118         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4119         
4120         pic16_emitpLabel(label1->key);
4121         
4122         emitCLRC;
4123         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4124
4125
4126         emitCLRC;
4127         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4128         
4129
4130         emitSKPNC;
4131         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4132         
4133         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4134         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4135         
4136         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4137         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4138         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4139         
4140         pic16_emitpLabel( label3->key );
4141         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4142         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4143         
4144         
4145
4146         pic16_emitpLabel(label2->key);
4147         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4148         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4149         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4150         
4151         /* result is in wreg */
4152         if(AOP_TYPE(result) != AOP_ACC)
4153                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4154
4155         pic16_popReleaseTempReg( pct3, 1);
4156         pic16_popReleaseTempReg( pct2, 1);
4157         pic16_popReleaseTempReg( pct1, 1);
4158
4159         return ;
4160     }
4161
4162     /* signed is a little bit more difficult */
4163
4164     /* save the signs of the operands */
4165     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4166     MOVA(l);    
4167     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4168     pic16_emitcode("push","acc"); /* save it on the stack */
4169
4170     /* now sign adjust for both left & right */
4171     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4172     MOVA(l);       
4173     lbl = newiTempLabel(NULL);
4174     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4175     pic16_emitcode("cpl","a");   
4176     pic16_emitcode("inc","a");
4177     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4178     pic16_emitcode("mov","b,a");
4179
4180     /* sign adjust left side */
4181     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4182     MOVA(l);
4183
4184     lbl = newiTempLabel(NULL);
4185     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4186     pic16_emitcode("cpl","a");
4187     pic16_emitcode("inc","a");
4188     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4189
4190     /* now the division */
4191     pic16_emitcode("div","ab");
4192     /* we are interested in the lower order
4193     only */
4194     pic16_emitcode("mov","b,a");
4195     lbl = newiTempLabel(NULL);
4196     pic16_emitcode("pop","acc");   
4197     /* if there was an over flow we don't 
4198     adjust the sign of the result */
4199     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4200     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4201     CLRC;
4202     pic16_emitcode("clr","a");
4203     pic16_emitcode("subb","a,b");
4204     pic16_emitcode("mov","b,a");
4205     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4206
4207     /* now we are done */
4208     pic16_aopPut(AOP(result),"b",0);
4209     if(size > 0){
4210         pic16_emitcode("mov","c,b.7");
4211         pic16_emitcode("subb","a,acc");   
4212     }
4213     while (size--)
4214         pic16_aopPut(AOP(result),"a",offset++);
4215
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genDiv - generates code for division                            */
4220 /*-----------------------------------------------------------------*/
4221 static void genDiv (iCode *ic)
4222 {
4223     operand *left = IC_LEFT(ic);
4224     operand *right = IC_RIGHT(ic);
4225     operand *result= IC_RESULT(ic);   
4226
4227
4228         /* Division is a very lengthy algorithm, so it is better
4229          * to call support routines than inlining algorithm.
4230          * Division functions written here just in case someone
4231          * wants to inline and not use the support libraries -- VR */
4232
4233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4234     /* assign the amsops */
4235     pic16_aopOp (left,ic,FALSE);
4236     pic16_aopOp (right,ic,FALSE);
4237     pic16_aopOp (result,ic,TRUE);
4238
4239     /* special cases first */
4240     /* both are bits */
4241     if (AOP_TYPE(left) == AOP_CRY &&
4242         AOP_TYPE(right)== AOP_CRY) {
4243         genDivbits(left,right,result);
4244         goto release ;
4245     }
4246
4247     /* if both are of size == 1 */
4248     if (AOP_SIZE(left) == 1 &&
4249         AOP_SIZE(right) == 1 ) {
4250         genDivOneByte(left,right,result);
4251         goto release ;
4252     }
4253
4254     /* should have been converted to function call */
4255     assert(0);
4256 release :
4257     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4258     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4259     pic16_freeAsmop(result,NULL,ic,TRUE); 
4260 }
4261
4262 /*-----------------------------------------------------------------*/
4263 /* genModbits :- modulus of bits                                   */
4264 /*-----------------------------------------------------------------*/
4265 static void genModbits (operand *left, 
4266                         operand *right, 
4267                         operand *result)
4268 {
4269
4270     char *l;
4271
4272     /* the result must be bit */    
4273     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4274     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4275
4276     MOVA(l);       
4277
4278     pic16_emitcode("div","ab");
4279     pic16_emitcode("mov","a,b");
4280     pic16_emitcode("rrc","a");
4281     pic16_aopPut(AOP(result),"c",0);
4282 }
4283
4284 /*-----------------------------------------------------------------*/
4285 /* genModOneByte : 8 bit modulus                                   */
4286 /*-----------------------------------------------------------------*/
4287 static void genModOneByte (operand *left,
4288                            operand *right,
4289                            operand *result)
4290 {
4291     sym_link *opetype = operandType(result);
4292     char *l ;
4293     symbol *lbl ;
4294
4295     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4296     /* signed or unsigned */
4297     if (SPEC_USIGN(opetype)) {
4298         /* unsigned is easy */
4299         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4300         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4301         MOVA(l);    
4302         pic16_emitcode("div","ab");
4303         pic16_aopPut(AOP(result),"b",0);
4304         return ;
4305     }
4306
4307     /* signed is a little bit more difficult */
4308
4309     /* save the signs of the operands */
4310     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4311     MOVA(l);
4312
4313     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4314     pic16_emitcode("push","acc"); /* save it on the stack */
4315
4316     /* now sign adjust for both left & right */
4317     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4318     MOVA(l);
4319
4320     lbl = newiTempLabel(NULL);
4321     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4322     pic16_emitcode("cpl","a");   
4323     pic16_emitcode("inc","a");
4324     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4325     pic16_emitcode("mov","b,a"); 
4326
4327     /* sign adjust left side */
4328     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4329     MOVA(l);
4330
4331     lbl = newiTempLabel(NULL);
4332     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4333     pic16_emitcode("cpl","a");   
4334     pic16_emitcode("inc","a");
4335     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4336
4337     /* now the multiplication */
4338     pic16_emitcode("div","ab");
4339     /* we are interested in the lower order
4340     only */
4341     lbl = newiTempLabel(NULL);
4342     pic16_emitcode("pop","acc");   
4343     /* if there was an over flow we don't 
4344     adjust the sign of the result */
4345     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4346     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4347     CLRC ;
4348     pic16_emitcode("clr","a");
4349     pic16_emitcode("subb","a,b");
4350     pic16_emitcode("mov","b,a");
4351     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4352
4353     /* now we are done */
4354     pic16_aopPut(AOP(result),"b",0);
4355
4356 }
4357
4358 /*-----------------------------------------------------------------*/
4359 /* genMod - generates code for division                            */
4360 /*-----------------------------------------------------------------*/
4361 static void genMod (iCode *ic)
4362 {
4363     operand *left = IC_LEFT(ic);
4364     operand *right = IC_RIGHT(ic);
4365     operand *result= IC_RESULT(ic);  
4366
4367     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4368     /* assign the amsops */
4369     pic16_aopOp (left,ic,FALSE);
4370     pic16_aopOp (right,ic,FALSE);
4371     pic16_aopOp (result,ic,TRUE);
4372
4373     /* special cases first */
4374     /* both are bits */
4375     if (AOP_TYPE(left) == AOP_CRY &&
4376         AOP_TYPE(right)== AOP_CRY) {
4377         genModbits(left,right,result);
4378         goto release ;
4379     }
4380
4381     /* if both are of size == 1 */
4382     if (AOP_SIZE(left) == 1 &&
4383         AOP_SIZE(right) == 1 ) {
4384         genModOneByte(left,right,result);
4385         goto release ;
4386     }
4387
4388     /* should have been converted to function call */
4389     assert(0);
4390
4391 release :
4392     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4393     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4394     pic16_freeAsmop(result,NULL,ic,TRUE); 
4395 }
4396
4397 /*-----------------------------------------------------------------*/
4398 /* genIfxJump :- will create a jump depending on the ifx           */
4399 /*-----------------------------------------------------------------*/
4400 /*
4401   note: May need to add parameter to indicate when a variable is in bit space.
4402 */
4403 static void genIfxJump (iCode *ic, char *jval)
4404 {
4405
4406     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4407     /* if true label then we jump if condition
4408     supplied is true */
4409     if ( IC_TRUE(ic) ) {
4410
4411         if(strcmp(jval,"a") == 0)
4412           emitSKPZ;
4413         else if (strcmp(jval,"c") == 0)
4414           emitSKPC;
4415         else {
4416           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4417           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4418         }
4419
4420         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4421         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4422
4423     }
4424     else {
4425         /* false label is present */
4426         if(strcmp(jval,"a") == 0)
4427           emitSKPNZ;
4428         else if (strcmp(jval,"c") == 0)
4429           emitSKPNC;
4430         else {
4431           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4432           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4433         }
4434
4435         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4436         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4437
4438     }
4439
4440
4441     /* mark the icode as generated */
4442     ic->generated = 1;
4443 }
4444
4445 #if 0
4446 // not needed ATM
4447
4448 /*-----------------------------------------------------------------*/
4449 /* genSkip                                                         */
4450 /*-----------------------------------------------------------------*/
4451 static void genSkip(iCode *ifx,int status_bit)
4452 {
4453   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4454   if(!ifx)
4455     return;
4456
4457   if ( IC_TRUE(ifx) ) {
4458     switch(status_bit) {
4459     case 'z':
4460       emitSKPNZ;
4461       break;
4462
4463     case 'c':
4464       emitSKPNC;
4465       break;
4466
4467     case 'd':
4468       emitSKPDC;
4469       break;
4470
4471     }
4472
4473     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4474     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4475
4476   } else {
4477
4478     switch(status_bit) {
4479
4480     case 'z':
4481       emitSKPZ;
4482       break;
4483
4484     case 'c':
4485       emitSKPC;
4486       break;
4487
4488     case 'd':
4489       emitSKPDC;
4490       break;
4491     }
4492     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4493     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4494
4495   }
4496
4497 }
4498 #endif
4499
4500 /*-----------------------------------------------------------------*/
4501 /* genSkipc                                                        */
4502 /*-----------------------------------------------------------------*/
4503 static void genSkipc(resolvedIfx *rifx)
4504 {
4505   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4506   
4507   if(!rifx)
4508     return;
4509
4510   if(rifx->condition)
4511     emitSKPC;
4512   else
4513     emitSKPNC;
4514
4515   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4516   rifx->generated = 1;
4517 }
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genSkipz2                                                       */
4521 /*-----------------------------------------------------------------*/
4522 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4523 {
4524   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4525   
4526   if(!rifx)
4527     return;
4528
4529   if( (rifx->condition ^ invert_condition) & 1)
4530     emitSKPZ;
4531   else
4532     emitSKPNZ;
4533
4534   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4535   rifx->generated = 1;
4536 }
4537
4538 #if 0
4539 /*-----------------------------------------------------------------*/
4540 /* genSkipz                                                        */
4541 /*-----------------------------------------------------------------*/
4542 static void genSkipz(iCode *ifx, int condition)
4543 {
4544   if(!ifx)
4545     return;
4546
4547   if(condition)
4548     emitSKPNZ;
4549   else
4550     emitSKPZ;
4551
4552   if ( IC_TRUE(ifx) )
4553     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4554   else
4555     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4556
4557   if ( IC_TRUE(ifx) )
4558     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4559   else
4560     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4561
4562 }
4563 #endif
4564
4565 /*-----------------------------------------------------------------*/
4566 /* genSkipCond                                                     */
4567 /*-----------------------------------------------------------------*/
4568 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4569 {
4570   if(!rifx)
4571     return;
4572
4573   if(rifx->condition)
4574     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4575   else
4576     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4577
4578
4579   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4580   rifx->generated = 1;
4581 }
4582
4583 #if 0
4584 /*-----------------------------------------------------------------*/
4585 /* genChkZeroes :- greater or less than comparison                 */
4586 /*     For each byte in a literal that is zero, inclusive or the   */
4587 /*     the corresponding byte in the operand with W                */
4588 /*     returns true if any of the bytes are zero                   */
4589 /*-----------------------------------------------------------------*/
4590 static int genChkZeroes(operand *op, int lit,  int size)
4591 {
4592
4593   int i;
4594   int flag =1;
4595
4596   while(size--) {
4597     i = (lit >> (size*8)) & 0xff;
4598
4599     if(i==0) {
4600       if(flag) 
4601         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4602       else
4603         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4604       flag = 0;
4605     }
4606   }
4607
4608   return (flag==0);
4609 }
4610 #endif
4611
4612 /*-----------------------------------------------------------------*/
4613 /* genCmp :- greater or less than comparison                       */
4614 /*-----------------------------------------------------------------*/
4615 #if 1
4616 static void genCmp (operand *left,operand *right,
4617                     operand *result, iCode *ifx, int sign)
4618 {
4619   int size; //, offset = 0 ;
4620   unsigned long lit = 0L,i = 0;
4621   resolvedIfx rFalseIfx;
4622   //  resolvedIfx rTrueIfx;
4623   symbol *truelbl;
4624   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4625 /*
4626   if(ifx) {
4627     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4628     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4629   }
4630 */
4631
4632   resolveIfx(&rFalseIfx,ifx);
4633   truelbl  = newiTempLabel(NULL);
4634   size = max(AOP_SIZE(left),AOP_SIZE(right));
4635
4636   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4637
4638 #define _swapp
4639
4640   /* if literal is on the right then swap with left */
4641   if ((AOP_TYPE(right) == AOP_LIT)) {
4642     operand *tmp = right ;
4643     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4644     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4645 #ifdef _swapp
4646
4647     lit = (lit - 1) & mask;
4648     right = left;
4649     left = tmp;
4650     rFalseIfx.condition ^= 1;
4651 #endif
4652
4653   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4654     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4655   }
4656
4657
4658   //if(IC_TRUE(ifx) == NULL)
4659   /* if left & right are bit variables */
4660   if (AOP_TYPE(left) == AOP_CRY &&
4661       AOP_TYPE(right) == AOP_CRY ) {
4662     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4663     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4664   } else {
4665     /* subtract right from left if at the
4666        end the carry flag is set then we know that
4667        left is greater than right */
4668
4669     symbol *lbl  = newiTempLabel(NULL);
4670
4671 #if 0
4672         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4673                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4674 #endif
4675
4676 #ifndef _swapp
4677     if(AOP_TYPE(right) == AOP_LIT) {
4678
4679       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4680
4681       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4682
4683       /* special cases */
4684
4685       if(lit == 0) {
4686
4687         if(sign != 0) 
4688           genSkipCond(&rFalseIfx,left,size-1,7);
4689         else 
4690           /* no need to compare to 0...*/
4691           /* NOTE: this is a de-generate compare that most certainly 
4692            *       creates some dead code. */
4693           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4694
4695         if(ifx) ifx->generated = 1;
4696         return;
4697
4698       }
4699       size--;
4700
4701       if(size == 0) {
4702         //i = (lit >> (size*8)) & 0xff;
4703         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4704         
4705         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4706
4707         i = ((0-lit) & 0xff);
4708         if(sign) {
4709           if( i == 0x81) { 
4710             /* lit is 0x7f, all signed chars are less than
4711              * this except for 0x7f itself */
4712             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4713             genSkipz2(&rFalseIfx,0);
4714           } else {
4715             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4716             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4717             genSkipc(&rFalseIfx);
4718           }
4719
4720         } else {
4721           if(lit == 1) {
4722             genSkipz2(&rFalseIfx,1);
4723           } else {
4724             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4725             genSkipc(&rFalseIfx);
4726           }
4727         }
4728
4729         if(ifx) ifx->generated = 1;
4730         return;
4731       }
4732
4733       /* chars are out of the way. now do ints and longs */
4734
4735
4736       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4737         
4738       /* special cases */
4739
4740       if(sign) {
4741
4742         if(lit == 0) {
4743           genSkipCond(&rFalseIfx,left,size,7);
4744           if(ifx) ifx->generated = 1;
4745           return;
4746         }
4747
4748         if(lit <0x100) {
4749           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4750
4751           //rFalseIfx.condition ^= 1;
4752           //genSkipCond(&rFalseIfx,left,size,7);
4753           //rFalseIfx.condition ^= 1;
4754
4755           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4756           if(rFalseIfx.condition)
4757             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4758           else
4759             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4760
4761           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4762           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4763           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4764
4765           while(size > 1)
4766             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4767
4768           if(rFalseIfx.condition) {
4769             emitSKPZ;
4770             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4771
4772           } else {
4773             emitSKPNZ;
4774           }
4775
4776           genSkipc(&rFalseIfx);
4777           pic16_emitpLabel(truelbl->key);
4778           if(ifx) ifx->generated = 1;
4779           return;
4780
4781         }
4782
4783         if(size == 1) {
4784
4785           if( (lit & 0xff) == 0) {
4786             /* lower byte is zero */
4787             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4788             i = ((lit >> 8) & 0xff) ^0x80;
4789             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4790             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4791             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4792             genSkipc(&rFalseIfx);
4793
4794
4795             if(ifx) ifx->generated = 1;
4796             return;
4797
4798           }
4799         } else {
4800           /* Special cases for signed longs */
4801           if( (lit & 0xffffff) == 0) {
4802             /* lower byte is zero */
4803             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4804             i = ((lit >> 8*3) & 0xff) ^0x80;
4805             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4806             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4807             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4808             genSkipc(&rFalseIfx);
4809
4810
4811             if(ifx) ifx->generated = 1;
4812             return;
4813
4814           }
4815
4816         }
4817
4818
4819         if(lit & (0x80 << (size*8))) {
4820           /* lit is negative */
4821           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4822
4823           //genSkipCond(&rFalseIfx,left,size,7);
4824
4825           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4826
4827           if(rFalseIfx.condition)
4828             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4829           else
4830             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4831
4832
4833         } else {
4834           /* lit is positive */
4835           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4836           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4837           if(rFalseIfx.condition)
4838             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4839           else
4840             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4841
4842         }
4843
4844         /*
4845           This works, but is only good for ints.
4846           It also requires a "known zero" register.
4847           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4848           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4849           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4850           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4851           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4852           genSkipc(&rFalseIfx);
4853
4854           pic16_emitpLabel(truelbl->key);
4855           if(ifx) ifx->generated = 1;
4856           return;
4857         **/
4858           
4859         /* There are no more special cases, so perform a general compare */
4860   
4861         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4862         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4863
4864         while(size--) {
4865
4866           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4867           emitSKPNZ;
4868           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4869         }
4870         //rFalseIfx.condition ^= 1;
4871         genSkipc(&rFalseIfx);
4872
4873         pic16_emitpLabel(truelbl->key);
4874
4875         if(ifx) ifx->generated = 1;
4876         return;
4877
4878
4879       }
4880
4881
4882       /* sign is out of the way. So now do an unsigned compare */
4883       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4884
4885
4886       /* General case - compare to an unsigned literal on the right.*/
4887
4888       i = (lit >> (size*8)) & 0xff;
4889       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4890       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4891       while(size--) {
4892         i = (lit >> (size*8)) & 0xff;
4893
4894         if(i) {
4895           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4896           emitSKPNZ;
4897           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4898         } else {
4899           /* this byte of the lit is zero, 
4900            *if it's not the last then OR in the variable */
4901           if(size)
4902             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4903         }
4904       }
4905
4906
4907       pic16_emitpLabel(lbl->key);
4908 //      pic16_emitpLabel(truelbl->key);
4909       //if(emitFinalCheck)
4910       genSkipc(&rFalseIfx);
4911       if(sign)
4912         pic16_emitpLabel(truelbl->key);
4913
4914       if(ifx) ifx->generated = 1;
4915       return;
4916
4917
4918     }
4919 #endif  // _swapp
4920
4921     if(AOP_TYPE(left) == AOP_LIT) {
4922       //symbol *lbl = newiTempLabel(NULL);
4923
4924       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4925
4926
4927       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4928
4929       /* Special cases */
4930       if((lit == 0) && (sign == 0)){
4931
4932         size--;
4933         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4934         while(size) 
4935           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4936
4937         genSkipz2(&rFalseIfx,0);
4938         if(ifx) ifx->generated = 1;
4939         return;
4940       }
4941
4942       if(size==1) {
4943         /* Special cases */
4944         lit &= 0xff;
4945         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4946           /* degenerate compare can never be true */
4947           if(rFalseIfx.condition == 0)
4948             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4949
4950           if(ifx) ifx->generated = 1;
4951           return;
4952         }
4953
4954         if(sign) {
4955           /* signed comparisons to a literal byte */
4956
4957           int lp1 = (lit+1) & 0xff;
4958
4959           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4960           switch (lp1) {
4961           case 0:
4962             rFalseIfx.condition ^= 1;
4963             genSkipCond(&rFalseIfx,right,0,7);
4964             break;
4965           case 0x7f:
4966             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4967             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4968             genSkipz2(&rFalseIfx,1);
4969             break;
4970           default:
4971             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4972             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4973             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4974             rFalseIfx.condition ^= 1;
4975             genSkipc(&rFalseIfx);
4976             break;
4977           }
4978         } else {
4979           /* unsigned comparisons to a literal byte */
4980
4981           switch(lit & 0xff ) {
4982           case 0:
4983             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4984             genSkipz2(&rFalseIfx,0);
4985             break;
4986           case 0x7f:
4987             rFalseIfx.condition ^= 1;
4988             genSkipCond(&rFalseIfx,right,0,7);
4989             break;
4990
4991           default:
4992             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4993             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4994             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4995             rFalseIfx.condition ^= 1;
4996             if (AOP_TYPE(result) == AOP_CRY)
4997               genSkipc(&rFalseIfx);
4998             else {
4999               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5000               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5001             }         
5002             break;
5003           }
5004         }
5005
5006         if(ifx) ifx->generated = 1;
5007         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5008                 goto check_carry;
5009         return;
5010
5011       } else {
5012
5013         /* Size is greater than 1 */
5014
5015         if(sign) {
5016           int lp1 = lit+1;
5017
5018           size--;
5019
5020           if(lp1 == 0) {
5021             /* this means lit = 0xffffffff, or -1 */
5022
5023
5024             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5025             rFalseIfx.condition ^= 1;
5026             genSkipCond(&rFalseIfx,right,size,7);
5027             if(ifx) ifx->generated = 1;
5028
5029             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5030               goto check_carry;
5031
5032             return;
5033           }
5034
5035           if(lit == 0) {
5036             int s = size;
5037
5038             if(rFalseIfx.condition) {
5039               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5040               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5041             }
5042
5043             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5044             while(size--)
5045               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5046
5047
5048             emitSKPZ;
5049             if(rFalseIfx.condition) {
5050               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5051               pic16_emitpLabel(truelbl->key);
5052             }else {
5053               rFalseIfx.condition ^= 1;
5054               genSkipCond(&rFalseIfx,right,s,7);
5055             }
5056
5057             if(ifx) ifx->generated = 1;
5058
5059             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5060               goto check_carry;
5061
5062             return;
5063           }
5064
5065           if((size == 1) &&  (0 == (lp1&0xff))) {
5066             /* lower byte of signed word is zero */
5067             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5068             i = ((lp1 >> 8) & 0xff) ^0x80;
5069             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5070             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5071             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5072             rFalseIfx.condition ^= 1;
5073             genSkipc(&rFalseIfx);
5074
5075
5076             if(ifx) ifx->generated = 1;
5077
5078             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5079               goto check_carry;
5080
5081             return;
5082           }
5083
5084           if(lit & (0x80 << (size*8))) {
5085             /* Lit is less than zero */
5086             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5087             //rFalseIfx.condition ^= 1;
5088             //genSkipCond(&rFalseIfx,left,size,7);
5089             //rFalseIfx.condition ^= 1;
5090             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5091             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5092
5093             if(rFalseIfx.condition)
5094               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5095             else
5096               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5097
5098
5099           } else {
5100             /* Lit is greater than or equal to zero */
5101             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5102             //rFalseIfx.condition ^= 1;
5103             //genSkipCond(&rFalseIfx,right,size,7);
5104             //rFalseIfx.condition ^= 1;
5105
5106             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5107             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5108
5109             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5110             if(rFalseIfx.condition)
5111               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5112             else
5113               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5114
5115           }
5116
5117
5118           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5119           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5120
5121           while(size--) {
5122
5123             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5124             emitSKPNZ;
5125             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5126           }
5127           rFalseIfx.condition ^= 1;
5128           //rFalseIfx.condition = 1;
5129           genSkipc(&rFalseIfx);
5130
5131           pic16_emitpLabel(truelbl->key);
5132
5133           if(ifx) ifx->generated = 1;
5134
5135
5136           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5137             goto check_carry;
5138
5139           return;
5140           // end of if (sign)
5141         } else {
5142
5143           /* compare word or long to an unsigned literal on the right.*/
5144
5145
5146           size--;
5147           if(lit < 0xff) {
5148             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5149             switch (lit) {
5150             case 0:
5151               break; /* handled above */
5152 /*
5153             case 0xff:
5154               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5155               while(size--)
5156                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5157               genSkipz2(&rFalseIfx,0);
5158               break;
5159 */
5160             default:
5161               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5162               while(--size)
5163                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5164
5165               emitSKPZ;
5166               if(rFalseIfx.condition)
5167                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5168               else
5169                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5170
5171
5172               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5173               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5174
5175               rFalseIfx.condition ^= 1;
5176               genSkipc(&rFalseIfx);
5177             }
5178
5179             pic16_emitpLabel(truelbl->key);
5180
5181             if(ifx) ifx->generated = 1;
5182
5183             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5184               goto check_carry;
5185
5186             return;
5187           }
5188
5189
5190           lit++;
5191           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5192           i = (lit >> (size*8)) & 0xff;
5193
5194           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5195           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5196
5197           while(size--) {
5198             i = (lit >> (size*8)) & 0xff;
5199
5200             if(i) {
5201               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5202               emitSKPNZ;
5203               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5204             } else {
5205               /* this byte of the lit is zero, 
5206                * if it's not the last then OR in the variable */
5207               if(size)
5208                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5209             }
5210           }
5211
5212
5213           pic16_emitpLabel(lbl->key);
5214
5215           rFalseIfx.condition ^= 1;
5216
5217           genSkipc(&rFalseIfx);
5218         }
5219
5220         if(sign)
5221           pic16_emitpLabel(truelbl->key);
5222         if(ifx) ifx->generated = 1;
5223
5224             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5225               goto check_carry;
5226
5227         return;
5228       }
5229     }
5230     /* Compare two variables */
5231
5232     DEBUGpic16_emitcode(";sign","%d",sign);
5233
5234     size--;
5235     if(sign) {
5236       /* Sigh. thus sucks... */
5237       if(size) {
5238         pCodeOp *pctemp;
5239         
5240         pctemp = pic16_popGetTempReg(1);
5241         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5242         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5243         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5244         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5245         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5246         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5247         pic16_popReleaseTempReg(pctemp, 1);
5248       } else {
5249         /* Signed char comparison */
5250         /* Special thanks to Nikolai Golovchenko for this snippet */
5251         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5252         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5253         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5254         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5255         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5256         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5257
5258         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5259         genSkipc(&rFalseIfx);
5260           
5261         if(ifx) ifx->generated = 1;
5262
5263             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5264               goto check_carry;
5265
5266         return;
5267       }
5268
5269     } else {
5270
5271       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5272       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5273     }
5274
5275
5276     /* The rest of the bytes of a multi-byte compare */
5277     while (size) {
5278
5279       emitSKPZ;
5280       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5281       size--;
5282
5283       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5284       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5285
5286
5287     }
5288
5289     pic16_emitpLabel(lbl->key);
5290
5291     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5292     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5293         (AOP_TYPE(result) == AOP_REG)) {
5294       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5295       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5296     } else {
5297       genSkipc(&rFalseIfx);
5298     }         
5299     //genSkipc(&rFalseIfx);
5300     if(ifx) ifx->generated = 1;
5301
5302
5303             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5304               goto check_carry;
5305
5306     return;
5307
5308   }
5309
5310 check_carry:
5311   if ((AOP_TYPE(result) != AOP_CRY) 
5312         && AOP_SIZE(result)) {
5313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5314
5315     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5316
5317     pic16_outBitC(result);
5318   } else {
5319     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5320     /* if the result is used in the next
5321        ifx conditional branch then generate
5322        code a little differently */
5323     if (ifx )
5324       genIfxJump (ifx,"c");
5325     else
5326       pic16_outBitC(result);
5327     /* leave the result in acc */
5328   }
5329
5330 }
5331
5332 #else   /* old version of genCmp() */
5333
5334 /* new version of genCmp -- VR 20041012 */
5335 static void genCmp (operand *left,operand *right,
5336                     operand *result, iCode *ifx, int sign)
5337 {
5338   int size; //, offset = 0 ;
5339   unsigned long lit = 0L,i = 0;
5340   resolvedIfx rFalseIfx;
5341   int willCheckCarry=0;
5342   //  resolvedIfx rTrueIfx;
5343   symbol *truelbl;
5344   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5345
5346
5347   /* General concept:
5348    * subtract right from left if at the end the carry flag is set then we
5349    * know that left is greater than right */
5350             
5351   resolveIfx(&rFalseIfx,ifx);
5352   truelbl  = newiTempLabel(NULL);
5353   size = max(AOP_SIZE(left),AOP_SIZE(right));
5354
5355   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5356
5357   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5358    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5359   
5360
5361   /* if literal is on the right then swap with left */
5362   if ((AOP_TYPE(right) == AOP_LIT)) {
5363     operand *tmp = right ;
5364     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5365
5366       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5367
5368 //      lit = (lit - 1) & mask;
5369       right = left;
5370       left = tmp;
5371       rFalseIfx.condition ^= 1;
5372   } else
5373   if ((AOP_TYPE(left) == AOP_LIT)) {
5374     /* float compares are handled by support functions */
5375     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5376   }
5377
5378
5379   //if(IC_TRUE(ifx) == NULL)
5380   /* if left & right are bit variables */
5381   if (AOP_TYPE(left) == AOP_CRY &&
5382       AOP_TYPE(right) == AOP_CRY ) {
5383     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5384     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5385
5386   } else {
5387     symbol *lbl  = newiTempLabel(NULL);
5388
5389     if(AOP_TYPE(left) == AOP_LIT) {
5390       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5391
5392       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5393         willCheckCarry = 1;
5394       else willCheckCarry = 0;
5395
5396       /* Special cases */
5397       if((lit == 0) && (sign == 0)){
5398
5399         size--;
5400         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5401         while(size) 
5402           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5403
5404         genSkipz2(&rFalseIfx,0);
5405         if(ifx) ifx->generated = 1;
5406         return;
5407       }
5408
5409       if(size==1) {
5410         /* Special cases */
5411         lit &= 0xff;
5412         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5413           /* degenerate compare can never be true */
5414           if(rFalseIfx.condition == 0)
5415             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5416
5417           if(ifx) ifx->generated = 1;
5418           return;
5419         }
5420
5421         if(sign) {
5422           /* signed comparisons to a literal byte */
5423
5424           int lp1 = (lit+1) & 0xff;
5425
5426           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d",__LINE__,lit, rFalseIfx.condition);
5427           switch (lp1) {
5428           case 0:
5429             rFalseIfx.condition ^= 1;
5430             genSkipCond(&rFalseIfx,right,0,7);
5431             break;
5432           case 0x7f:
5433             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5434             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5435             genSkipz2(&rFalseIfx,1);
5436             break;
5437           default:
5438             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5439             
5440             if(rFalseIfx.condition)
5441               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5442             else
5443               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5444
5445             if(willCheckCarry) {
5446               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5447               else { emitSETC; emitCLRC; }
5448               
5449             } else {
5450               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5451             }              
5452                       
5453 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5454             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5455             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5456             rFalseIfx.condition ^= 1;
5457             genSkipc(&rFalseIfx);
5458 */
5459             break;
5460           }
5461         } else {
5462           /* unsigned comparisons to a literal byte */
5463
5464           switch(lit & 0xff ) {
5465           case 0:
5466             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5467             genSkipz2(&rFalseIfx,0);
5468             break;
5469           case 0x7f:
5470             rFalseIfx.condition ^= 1;
5471             genSkipCond(&rFalseIfx,right,0,7);
5472             break;
5473
5474           default:
5475             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5476             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5477             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5478             rFalseIfx.condition ^= 1;
5479             if (AOP_TYPE(result) == AOP_CRY)
5480               genSkipc(&rFalseIfx);
5481             else {
5482               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5483               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5484             }         
5485             break;
5486           }
5487         }
5488
5489         if(ifx) ifx->generated = 1;
5490         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5491                 goto check_carry;
5492         return;
5493
5494       } else {
5495
5496         /* Size is greater than 1 */
5497
5498         if(sign) {
5499           int lp1 = lit+1;
5500
5501           size--;
5502
5503           if(lp1 == 0) {
5504             /* this means lit = 0xffffffff, or -1 */
5505
5506
5507             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5508             rFalseIfx.condition ^= 1;
5509             genSkipCond(&rFalseIfx,right,size,7);
5510             if(ifx) ifx->generated = 1;
5511             return;
5512           }
5513
5514           if(lit == 0) {
5515             int s = size;
5516
5517             if(rFalseIfx.condition) {
5518               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5519               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5520             }
5521
5522             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5523             while(size--)
5524               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5525
5526
5527             emitSKPZ;
5528             if(rFalseIfx.condition) {
5529               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5530               pic16_emitpLabel(truelbl->key);
5531             }else {
5532               rFalseIfx.condition ^= 1;
5533               genSkipCond(&rFalseIfx,right,s,7);
5534             }
5535
5536             if(ifx) ifx->generated = 1;
5537             return;
5538           }
5539
5540           if((size == 1) &&  (0 == (lp1&0xff))) {
5541             /* lower byte of signed word is zero */
5542             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5543             i = ((lp1 >> 8) & 0xff) ^0x80;
5544             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5545             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5546             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5547             rFalseIfx.condition ^= 1;
5548             genSkipc(&rFalseIfx);
5549
5550
5551             if(ifx) ifx->generated = 1;
5552             return;
5553           }
5554
5555           if(lit & (0x80 << (size*8))) {
5556             /* Lit is less than zero */
5557             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5558             //rFalseIfx.condition ^= 1;
5559             //genSkipCond(&rFalseIfx,left,size,7);
5560             //rFalseIfx.condition ^= 1;
5561             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5562             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5563
5564             if(rFalseIfx.condition)
5565               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5566             else
5567               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5568
5569
5570           } else {
5571             /* Lit is greater than or equal to zero */
5572             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5573             //rFalseIfx.condition ^= 1;
5574             //genSkipCond(&rFalseIfx,right,size,7);
5575             //rFalseIfx.condition ^= 1;
5576
5577             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5578             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5579
5580             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5581             if(rFalseIfx.condition)
5582               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5583             else
5584               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5585
5586           }
5587
5588
5589           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5590           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5591
5592           while(size--) {
5593
5594             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5595             emitSKPNZ;
5596             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5597           }
5598           rFalseIfx.condition ^= 1;
5599           //rFalseIfx.condition = 1;
5600           genSkipc(&rFalseIfx);
5601
5602           pic16_emitpLabel(truelbl->key);
5603
5604           if(ifx) ifx->generated = 1;
5605           return;
5606           // end of if (sign)
5607         } else {
5608
5609           /* compare word or long to an unsigned literal on the right.*/
5610
5611
5612           size--;
5613           if(lit < 0xff) {
5614             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5615             switch (lit) {
5616             case 0:
5617               break; /* handled above */
5618 /*
5619             case 0xff:
5620               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5621               while(size--)
5622                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5623               genSkipz2(&rFalseIfx,0);
5624               break;
5625 */
5626             default:
5627               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5628               while(--size)
5629                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5630
5631               emitSKPZ;
5632               if(rFalseIfx.condition)
5633                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5634               else
5635                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5636
5637
5638               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5639               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5640
5641               rFalseIfx.condition ^= 1;
5642               genSkipc(&rFalseIfx);
5643             }
5644
5645             pic16_emitpLabel(truelbl->key);
5646
5647             if(ifx) ifx->generated = 1;
5648             return;
5649           }
5650
5651
5652           lit++;
5653           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5654           i = (lit >> (size*8)) & 0xff;
5655
5656           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5657           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5658
5659           while(size--) {
5660             i = (lit >> (size*8)) & 0xff;
5661
5662             if(i) {
5663               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5664               emitSKPNZ;
5665               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5666             } else {
5667               /* this byte of the lit is zero, 
5668                * if it's not the last then OR in the variable */
5669               if(size)
5670                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5671             }
5672           }
5673
5674
5675           pic16_emitpLabel(lbl->key);
5676
5677           rFalseIfx.condition ^= 1;
5678
5679           genSkipc(&rFalseIfx);
5680         }
5681
5682         if(sign)
5683           pic16_emitpLabel(truelbl->key);
5684         if(ifx) ifx->generated = 1;
5685         return;
5686       }
5687     }
5688     /* Compare two variables */
5689
5690     DEBUGpic16_emitcode(";sign","%d",sign);
5691
5692     size--;
5693     if(sign) {
5694       /* Sigh. thus sucks... */
5695       if(size) {
5696         pCodeOp *pctemp;
5697         
5698         pctemp = pic16_popGetTempReg(1);
5699         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5700         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5701         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5702         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5703         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5704         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5705         pic16_popReleaseTempReg(pctemp, 1);
5706       } else {
5707         /* Signed char comparison */
5708         /* Special thanks to Nikolai Golovchenko for this snippet */
5709         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5710         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5711         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5712         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5713         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5714         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5715
5716         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5717         genSkipc(&rFalseIfx);
5718           
5719         if(ifx) ifx->generated = 1;
5720         return;
5721       }
5722
5723     } else {
5724
5725       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5726       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5727     }
5728
5729
5730     /* The rest of the bytes of a multi-byte compare */
5731     while (size) {
5732
5733       emitSKPZ;
5734       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5735       size--;
5736
5737       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5738       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5739
5740
5741     }
5742
5743     pic16_emitpLabel(lbl->key);
5744
5745     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5746     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5747         (AOP_TYPE(result) == AOP_REG)) {
5748       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5749       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5750     } else {
5751       genSkipc(&rFalseIfx);
5752     }         
5753     //genSkipc(&rFalseIfx);
5754     if(ifx) ifx->generated = 1;
5755
5756     return;
5757
5758   }
5759
5760 check_carry:
5761   if ((AOP_TYPE(result) != AOP_CRY) 
5762         && AOP_SIZE(result)) {
5763     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5764
5765     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5766
5767     pic16_outBitC(result);
5768   } else {
5769     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5770     /* if the result is used in the next
5771        ifx conditional branch then generate
5772        code a little differently */
5773     if (ifx )
5774       genIfxJump (ifx,"c");
5775     else
5776       pic16_outBitC(result);
5777     /* leave the result in acc */
5778   }
5779
5780 }
5781 #endif
5782
5783
5784
5785 /*-----------------------------------------------------------------*/
5786 /* genCmpGt :- greater than comparison                             */
5787 /*-----------------------------------------------------------------*/
5788 static void genCmpGt (iCode *ic, iCode *ifx)
5789 {
5790     operand *left, *right, *result;
5791     sym_link *letype , *retype;
5792     int sign ;
5793
5794     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5795     left = IC_LEFT(ic);
5796     right= IC_RIGHT(ic);
5797     result = IC_RESULT(ic);
5798
5799     letype = getSpec(operandType(left));
5800     retype =getSpec(operandType(right));
5801     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5802     /* assign the amsops */
5803     pic16_aopOp (left,ic,FALSE);
5804     pic16_aopOp (right,ic,FALSE);
5805     pic16_aopOp (result,ic,TRUE);
5806
5807     genCmp(right, left, result, ifx, sign);
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 /* genCmpLt - less than comparisons                                */
5816 /*-----------------------------------------------------------------*/
5817 static void genCmpLt (iCode *ic, iCode *ifx)
5818 {
5819     operand *left, *right, *result;
5820     sym_link *letype , *retype;
5821     int sign ;
5822
5823     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824     left = IC_LEFT(ic);
5825     right= IC_RIGHT(ic);
5826     result = IC_RESULT(ic);
5827
5828     letype = getSpec(operandType(left));
5829     retype =getSpec(operandType(right));
5830     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5831
5832     /* assign the amsops */
5833     pic16_aopOp (left,ic,FALSE);
5834     pic16_aopOp (right,ic,FALSE);
5835     pic16_aopOp (result,ic,TRUE);
5836
5837     genCmp(left, right, result, ifx, sign);
5838
5839     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5840     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5841     pic16_freeAsmop(result,NULL,ic,TRUE); 
5842 }
5843
5844 #if 0
5845 // not needed ATM
5846 // FIXME reenable literal optimisation when the pic16 port is stable
5847
5848 /*-----------------------------------------------------------------*/
5849 /* genc16bit2lit - compare a 16 bit value to a literal             */
5850 /*-----------------------------------------------------------------*/
5851 static void genc16bit2lit(operand *op, int lit, int offset)
5852 {
5853   int i;
5854
5855   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5856   if( (lit&0xff) == 0) 
5857     i=1;
5858   else
5859     i=0;
5860
5861   switch( BYTEofLONG(lit,i)) { 
5862   case 0:
5863     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5864     break;
5865   case 1:
5866     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5867     break;
5868   case 0xff:
5869     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5870     break;
5871   default:
5872     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5873     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5874   }
5875
5876   i ^= 1;
5877
5878   switch( BYTEofLONG(lit,i)) { 
5879   case 0:
5880     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5881     break;
5882   case 1:
5883     emitSKPNZ;
5884     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5885     break;
5886   case 0xff:
5887     emitSKPNZ;
5888     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5889     break;
5890   default:
5891     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5892     emitSKPNZ;
5893     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5894
5895   }
5896
5897 }
5898 #endif
5899
5900 #if 0
5901 // not needed ATM
5902 /*-----------------------------------------------------------------*/
5903 /* gencjneshort - compare and jump if not equal                    */
5904 /*-----------------------------------------------------------------*/
5905 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5906 {
5907   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5908   int offset = 0;
5909   int res_offset = 0;  /* the result may be a different size then left or right */
5910   int res_size = AOP_SIZE(result);
5911   resolvedIfx rIfx;
5912   symbol *lbl, *lbl_done;
5913
5914   unsigned long lit = 0L;
5915   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5916
5917   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5918   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5919   if(result)
5920     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5921   resolveIfx(&rIfx,ifx);
5922   lbl =  newiTempLabel(NULL);
5923   lbl_done =  newiTempLabel(NULL);
5924
5925
5926   /* if the left side is a literal or 
5927      if the right is in a pointer register and left 
5928      is not */
5929   if ((AOP_TYPE(left) == AOP_LIT) || 
5930       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5931     operand *t = right;
5932     right = left;
5933     left = t;
5934   }
5935   if(AOP_TYPE(right) == AOP_LIT)
5936     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5937
5938   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5939     preserve_result = 1;
5940
5941   if(result && !preserve_result)
5942     {
5943       int i;
5944       for(i = 0; i < AOP_SIZE(result); i++)
5945         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5946     }
5947
5948
5949   /* if the right side is a literal then anything goes */
5950   if (AOP_TYPE(right) == AOP_LIT &&
5951       AOP_TYPE(left) != AOP_DIR ) {
5952     switch(size) {
5953     case 2:
5954       genc16bit2lit(left, lit, 0);
5955       emitSKPZ;
5956       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5957       break;
5958     default:
5959       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5960       while (size--) {
5961         if(lit & 0xff) {
5962           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5963           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5964         } else {
5965           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5966         }
5967
5968         emitSKPZ;
5969         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5970         offset++;
5971         if(res_offset < res_size-1)
5972           res_offset++;
5973         lit >>= 8;
5974       }
5975       break;
5976     }
5977   }
5978
5979   /* if the right side is in a register or in direct space or
5980      if the left is a pointer register & right is not */    
5981   else if (AOP_TYPE(right) == AOP_REG ||
5982            AOP_TYPE(right) == AOP_DIR || 
5983            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5984            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5985     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5986     int lbl_key = lbl->key;
5987
5988     if(result) {
5989       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5990       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5991     }else {
5992       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5993       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5994               __FUNCTION__,__LINE__);
5995       return;
5996     }
5997    
5998 /*     switch(size) { */
5999 /*     case 2: */
6000 /*       genc16bit2lit(left, lit, 0); */
6001 /*       emitSKPNZ; */
6002 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6003 /*       break; */
6004 /*     default: */
6005     while (size--) {
6006       int emit_skip=1;
6007       if((AOP_TYPE(left) == AOP_DIR) && 
6008          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6009
6010         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6011         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6012
6013       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6014             
6015         switch (lit & 0xff) {
6016         case 0:
6017           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6018           break;
6019         case 1:
6020           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6021           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6022           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6023           emit_skip=0;
6024           break;
6025         case 0xff:
6026           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6027           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6028           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6029           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6030           emit_skip=0;
6031           break;
6032         default:
6033           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6034           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6035         }
6036         lit >>= 8;
6037
6038       } else {
6039         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6040       }
6041       if(emit_skip) {
6042         if(AOP_TYPE(result) == AOP_CRY) {
6043           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6044           if(rIfx.condition)
6045             emitSKPNZ;
6046           else
6047             emitSKPZ;
6048           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6049         } else {
6050           /* fix me. probably need to check result size too */
6051           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6052           if(rIfx.condition)
6053             emitSKPZ;
6054           else
6055             emitSKPNZ;
6056           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6057           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6058         }
6059         if(ifx)
6060           ifx->generated=1;
6061       }
6062       emit_skip++;
6063       offset++;
6064       if(res_offset < res_size-1)
6065         res_offset++;
6066     }
6067 /*       break; */
6068 /*     } */
6069   } else if(AOP_TYPE(right) == AOP_REG &&
6070             AOP_TYPE(left) != AOP_DIR){
6071
6072     while(size--) {
6073       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6074       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6075       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6076       if(rIfx.condition)
6077         emitSKPNZ;
6078       else
6079         emitSKPZ;
6080       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6081       offset++;
6082       if(res_offset < res_size-1)
6083         res_offset++;
6084     }
6085       
6086   }else{
6087     /* right is a pointer reg need both a & b */
6088     while(size--) {
6089       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6090       if(strcmp(l,"b"))
6091         pic16_emitcode("mov","b,%s",l);
6092       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6093       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6094       offset++;
6095     }
6096   }
6097
6098   if(result && preserve_result)
6099     {
6100       int i;
6101       for(i = 0; i < AOP_SIZE(result); i++)
6102         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6103     }
6104
6105   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6106
6107   if(result && preserve_result)
6108     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6109
6110   if(!rIfx.condition)
6111     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6112
6113   pic16_emitpLabel(lbl->key);
6114
6115   if(result && preserve_result)
6116     {
6117       int i;
6118       for(i = 0; i < AOP_SIZE(result); i++)
6119         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6120
6121       pic16_emitpLabel(lbl_done->key);
6122    }
6123
6124   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6125
6126   if(ifx)
6127     ifx->generated = 1;
6128 }
6129 #endif
6130
6131 #if 0
6132 /*-----------------------------------------------------------------*/
6133 /* gencjne - compare and jump if not equal                         */
6134 /*-----------------------------------------------------------------*/
6135 static void gencjne(operand *left, operand *right, iCode *ifx)
6136 {
6137     symbol *tlbl  = newiTempLabel(NULL);
6138
6139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6140     gencjneshort(left, right, lbl);
6141
6142     pic16_emitcode("mov","a,%s",one);
6143     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6144     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6145     pic16_emitcode("clr","a");
6146     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6147
6148     pic16_emitpLabel(lbl->key);
6149     pic16_emitpLabel(tlbl->key);
6150
6151 }
6152 #endif
6153
6154
6155 /*-----------------------------------------------------------------*/
6156 /* is_LitOp - check if operand has to be treated as literal        */
6157 /*-----------------------------------------------------------------*/
6158 static bool is_LitOp(operand *op)
6159 {
6160   return (AOP_TYPE(op) == AOP_LIT)
6161       || ( (AOP_TYPE(op) == AOP_PCODE)
6162           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6163               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
6164 }
6165
6166 /*-----------------------------------------------------------------*/
6167 /* is_LitAOp - check if operand has to be treated as literal        */
6168 /*-----------------------------------------------------------------*/
6169 static bool is_LitAOp(asmop *aop)
6170 {
6171   return (aop->type == AOP_LIT)
6172       || ( (aop->type == AOP_PCODE)
6173           && ( (aop->aopu.pcop->type == PO_LITERAL)
6174               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
6175 }
6176
6177
6178
6179 /*-----------------------------------------------------------------*/
6180 /* genCmpEq - generates code for equal to                          */
6181 /*-----------------------------------------------------------------*/
6182 static void genCmpEq (iCode *ic, iCode *ifx)
6183 {
6184   operand *left, *right, *result;
6185   symbol *falselbl = newiTempLabel(NULL);
6186   symbol *donelbl = newiTempLabel(NULL);
6187
6188   int preserve_result = 0;
6189   int generate_result = 0;
6190   int i=0;
6191
6192   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6193   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6194   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6195  
6196   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6197   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6198
6199   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6200     {
6201       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6202       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6203       goto release;
6204     }
6205
6206   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6207     {
6208       operand *tmp = right ;
6209       right = left;
6210       left = tmp;
6211     }
6212
6213   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6214     preserve_result = 1;
6215
6216   if(result && AOP_SIZE(result))
6217     generate_result = 1;
6218
6219   if(generate_result && !preserve_result)
6220     {
6221       for(i = 0; i < AOP_SIZE(result); i++)
6222         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6223     }
6224
6225   for(i=0; i < AOP_SIZE(left); i++)
6226     {
6227       if(AOP_TYPE(left) != AOP_ACC)
6228         {
6229           if(is_LitOp(left))
6230             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6231           else
6232             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6233         }
6234       if(is_LitOp(right))
6235         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6236       else
6237         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6238
6239       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6240     }
6241
6242   // result == true
6243
6244   if(generate_result && preserve_result)
6245     {
6246       for(i = 0; i < AOP_SIZE(result); i++)
6247         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6248     }
6249
6250   if(generate_result)
6251     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6252
6253   if(generate_result && preserve_result)
6254     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6255
6256   if(ifx && IC_TRUE(ifx))
6257     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6258
6259   if(ifx && IC_FALSE(ifx))
6260     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6261
6262   pic16_emitpLabel(falselbl->key);
6263
6264   // result == false
6265
6266   if(ifx && IC_FALSE(ifx))
6267     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6268
6269   if(generate_result && preserve_result)
6270     {
6271       for(i = 0; i < AOP_SIZE(result); i++)
6272         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6273     }
6274
6275   pic16_emitpLabel(donelbl->key);
6276
6277   if(ifx)
6278     ifx->generated = 1;
6279
6280 release:
6281   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6282   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6283   pic16_freeAsmop(result,NULL,ic,TRUE);
6284
6285 }
6286
6287
6288 #if 0
6289 // old version kept for reference
6290
6291 /*-----------------------------------------------------------------*/
6292 /* genCmpEq - generates code for equal to                          */
6293 /*-----------------------------------------------------------------*/
6294 static void genCmpEq (iCode *ic, iCode *ifx)
6295 {
6296     operand *left, *right, *result;
6297     unsigned long lit = 0L;
6298     int size,offset=0;
6299     symbol *falselbl  = newiTempLabel(NULL);
6300
6301
6302     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6303
6304     if(ifx)
6305       DEBUGpic16_emitcode ("; ifx is non-null","");
6306     else
6307       DEBUGpic16_emitcode ("; ifx is null","");
6308
6309     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6310     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6311     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6312
6313     size = max(AOP_SIZE(left),AOP_SIZE(right));
6314
6315     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6316
6317     /* if literal, literal on the right or 
6318     if the right is in a pointer register and left 
6319     is not */
6320     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6321         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6322       operand *tmp = right ;
6323       right = left;
6324       left = tmp;
6325     }
6326
6327
6328     if(ifx && !AOP_SIZE(result)){
6329         symbol *tlbl;
6330         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6331         /* if they are both bit variables */
6332         if (AOP_TYPE(left) == AOP_CRY &&
6333             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6334                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6335             if(AOP_TYPE(right) == AOP_LIT){
6336                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6337                 if(lit == 0L){
6338                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6339                     pic16_emitcode("cpl","c");
6340                 } else if(lit == 1L) {
6341                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6342                 } else {
6343                     pic16_emitcode("clr","c");
6344                 }
6345                 /* AOP_TYPE(right) == AOP_CRY */
6346             } else {
6347                 symbol *lbl = newiTempLabel(NULL);
6348                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6349                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6350                 pic16_emitcode("cpl","c");
6351                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6352             }
6353             /* if true label then we jump if condition
6354             supplied is true */
6355             tlbl = newiTempLabel(NULL);
6356             if ( IC_TRUE(ifx) ) {
6357                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6358                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6359             } else {
6360                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6361                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6362             }
6363             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6364
6365                 {
6366                 /* left and right are both bit variables, result is carry */
6367                         resolvedIfx rIfx;
6368               
6369                         resolveIfx(&rIfx,ifx);
6370
6371                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6372                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6373                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6374                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6375                         genSkipz2(&rIfx,0);
6376                 }
6377         } else {
6378
6379                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6380
6381                         /* They're not both bit variables. Is the right a literal? */
6382                         if(AOP_TYPE(right) == AOP_LIT) {
6383                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6384             
6385                         switch(size) {
6386
6387                                 case 1:
6388                                         switch(lit & 0xff) {
6389                                                 case 1:
6390                                                                 if ( IC_TRUE(ifx) ) {
6391                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6392                                                                         emitSKPNZ;
6393                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6394                                                                 } else {
6395                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6396                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6397                                                                 }
6398                                                                 break;
6399                                                 case 0xff:
6400                                                                 if ( IC_TRUE(ifx) ) {
6401                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6402                                                                         emitSKPNZ;
6403                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6404                                                                 } else {
6405                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6406                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6407                                                                 }
6408                                                                 break;
6409                                                 default:
6410                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6411                                                                 if(lit)
6412                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6413                                                                 genSkip(ifx,'z');
6414                                         } // switch lit
6415
6416
6417                                         /* end of size == 1 */
6418                                         break;
6419               
6420                                 case 2:
6421                                         genc16bit2lit(left,lit,offset);
6422                                         genSkip(ifx,'z');
6423                                         break;
6424                                         /* end of size == 2 */
6425
6426                                 default:
6427                                         /* size is 4 */
6428                                         if(lit==0) {
6429                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6430                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6431                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6432                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6433                                                 genSkip(ifx,'z');
6434                                         } else {
6435                                                 /* search for patterns that can be optimized */
6436
6437                                                 genc16bit2lit(left,lit,0);
6438                                                 lit >>= 16;
6439                                                 if(lit) {
6440                                                                 if(IC_TRUE(ifx))
6441                                                                 emitSKPZ; // if hi word unequal
6442                                                                 else
6443                                                                 emitSKPNZ; // if hi word equal
6444                                                                 // fail early
6445                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6446                                                         genc16bit2lit(left,lit,2);
6447                                                         genSkip(ifx,'z');
6448                                                 } else {
6449                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6450                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6451                                                         genSkip(ifx,'z');
6452                                                 }
6453                                         }
6454                                                 pic16_emitpLabel(falselbl->key);
6455                                                 break;
6456
6457                         } // switch size
6458           
6459                         ifx->generated = 1;
6460                         goto release ;
6461             
6462
6463           } else if(AOP_TYPE(right) == AOP_CRY ) {
6464             /* we know the left is not a bit, but that the right is */
6465             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6466             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6467                       pic16_popGet(AOP(right),offset));
6468             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6469
6470             /* if the two are equal, then W will be 0 and the Z bit is set
6471              * we could test Z now, or go ahead and check the high order bytes if
6472              * the variable we're comparing is larger than a byte. */
6473
6474             while(--size)
6475               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6476
6477             if ( IC_TRUE(ifx) ) {
6478               emitSKPNZ;
6479               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6480               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6481             } else {
6482               emitSKPZ;
6483               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6484               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6485             }
6486
6487           } else {
6488             /* They're both variables that are larger than bits */
6489             int s = size;
6490
6491             tlbl = newiTempLabel(NULL);
6492
6493             while(size--) {
6494               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6495               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6496
6497               if ( IC_TRUE(ifx) ) {
6498                 if(size) {
6499                   emitSKPZ;
6500                 
6501                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6502
6503                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6504                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6505                 } else {
6506                   emitSKPNZ;
6507
6508                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6509
6510
6511                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6512                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6513                 }
6514               } else {
6515                 emitSKPZ;
6516
6517                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6518
6519                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6520                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6521               }
6522               offset++;
6523             }
6524             if(s>1 && IC_TRUE(ifx)) {
6525               pic16_emitpLabel(tlbl->key);
6526               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6527             }
6528           }
6529         }
6530         /* mark the icode as generated */
6531         ifx->generated = 1;
6532         goto release ;
6533     }
6534
6535     /* if they are both bit variables */
6536     if (AOP_TYPE(left) == AOP_CRY &&
6537         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6538         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6539         if(AOP_TYPE(right) == AOP_LIT){
6540             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6541             if(lit == 0L){
6542                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6543                 pic16_emitcode("cpl","c");
6544             } else if(lit == 1L) {
6545                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6546             } else {
6547                 pic16_emitcode("clr","c");
6548             }
6549             /* AOP_TYPE(right) == AOP_CRY */
6550         } else {
6551             symbol *lbl = newiTempLabel(NULL);
6552             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6553             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6554             pic16_emitcode("cpl","c");
6555             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6556         }
6557         /* c = 1 if egal */
6558         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6559             pic16_outBitC(result);
6560             goto release ;
6561         }
6562         if (ifx) {
6563             genIfxJump (ifx,"c");
6564             goto release ;
6565         }
6566         /* if the result is used in an arithmetic operation
6567         then put the result in place */
6568         pic16_outBitC(result);
6569     } else {
6570       
6571       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6572       gencjne(left,right,result,ifx);
6573 /*
6574       if(ifx) 
6575         gencjne(left,right,newiTempLabel(NULL));
6576       else {
6577         if(IC_TRUE(ifx)->key)
6578           gencjne(left,right,IC_TRUE(ifx)->key);
6579         else
6580           gencjne(left,right,IC_FALSE(ifx)->key);
6581         ifx->generated = 1;
6582         goto release ;
6583       }
6584       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6585         pic16_aopPut(AOP(result),"a",0);
6586         goto release ;
6587       }
6588
6589       if (ifx) {
6590         genIfxJump (ifx,"a");
6591         goto release ;
6592       }
6593 */
6594       /* if the result is used in an arithmetic operation
6595          then put the result in place */
6596 /*
6597       if (AOP_TYPE(result) != AOP_CRY) 
6598         pic16_outAcc(result);
6599 */
6600       /* leave the result in acc */
6601     }
6602
6603 release:
6604     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6605     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6606     pic16_freeAsmop(result,NULL,ic,TRUE);
6607 }
6608 #endif
6609
6610 /*-----------------------------------------------------------------*/
6611 /* ifxForOp - returns the icode containing the ifx for operand     */
6612 /*-----------------------------------------------------------------*/
6613 static iCode *ifxForOp ( operand *op, iCode *ic )
6614 {
6615     /* if true symbol then needs to be assigned */
6616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6617     if (IS_TRUE_SYMOP(op))
6618         return NULL ;
6619
6620     /* if this has register type condition and
6621     the next instruction is ifx with the same operand
6622     and live to of the operand is upto the ifx only then */
6623     if (ic->next
6624         && ic->next->op == IFX
6625         && IC_COND(ic->next)->key == op->key
6626         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6627         ) {
6628                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6629           return ic->next;
6630     }
6631
6632     if (ic->next &&
6633         ic->next->op == IFX &&
6634         IC_COND(ic->next)->key == op->key) {
6635       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6636       return ic->next;
6637     }
6638
6639     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6640     if (ic->next &&
6641         ic->next->op == IFX)
6642       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6643
6644     if (ic->next &&
6645         ic->next->op == IFX &&
6646         IC_COND(ic->next)->key == op->key) {
6647       DEBUGpic16_emitcode ("; "," key is okay");
6648       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6649                            OP_SYMBOL(op)->liveTo,
6650                            ic->next->seq);
6651     }
6652
6653 #if 0
6654     /* the code below is completely untested
6655      * it just allows ulong2fs.c compile -- VR */
6656          
6657     ic = ic->next;
6658     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6659                                         __FILE__, __FUNCTION__, __LINE__);
6660         
6661     /* if this has register type condition and
6662     the next instruction is ifx with the same operand
6663     and live to of the operand is upto the ifx only then */
6664     if (ic->next &&
6665         ic->next->op == IFX &&
6666         IC_COND(ic->next)->key == op->key &&
6667         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6668         return ic->next;
6669
6670     if (ic->next &&
6671         ic->next->op == IFX &&
6672         IC_COND(ic->next)->key == op->key) {
6673       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6674       return ic->next;
6675     }
6676
6677     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6678                                         __FILE__, __FUNCTION__, __LINE__);
6679
6680 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6681 #endif
6682
6683     return NULL;
6684 }
6685 /*-----------------------------------------------------------------*/
6686 /* genAndOp - for && operation                                     */
6687 /*-----------------------------------------------------------------*/
6688 static void genAndOp (iCode *ic)
6689 {
6690     operand *left,*right, *result;
6691 /*     symbol *tlbl; */
6692
6693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6694     /* note here that && operations that are in an
6695     if statement are taken away by backPatchLabels
6696     only those used in arthmetic operations remain */
6697     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6698     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6699     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6700
6701     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6702
6703     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6704     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6705     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6706
6707     /* if both are bit variables */
6708 /*     if (AOP_TYPE(left) == AOP_CRY && */
6709 /*         AOP_TYPE(right) == AOP_CRY ) { */
6710 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6711 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6712 /*         pic16_outBitC(result); */
6713 /*     } else { */
6714 /*         tlbl = newiTempLabel(NULL); */
6715 /*         pic16_toBoolean(left);     */
6716 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6717 /*         pic16_toBoolean(right); */
6718 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6719 /*         pic16_outBitAcc(result); */
6720 /*     } */
6721
6722     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6723     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6724     pic16_freeAsmop(result,NULL,ic,TRUE);
6725 }
6726
6727
6728 /*-----------------------------------------------------------------*/
6729 /* genOrOp - for || operation                                      */
6730 /*-----------------------------------------------------------------*/
6731 /*
6732   tsd pic port -
6733   modified this code, but it doesn't appear to ever get called
6734 */
6735
6736 static void genOrOp (iCode *ic)
6737 {
6738     operand *left,*right, *result;
6739     symbol *tlbl;
6740
6741     /* note here that || operations that are in an
6742     if statement are taken away by backPatchLabels
6743     only those used in arthmetic operations remain */
6744     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6745     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6746     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6747     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6748
6749     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6750
6751     /* if both are bit variables */
6752     if (AOP_TYPE(left) == AOP_CRY &&
6753         AOP_TYPE(right) == AOP_CRY ) {
6754       pic16_emitcode("clrc","");
6755       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6756                AOP(left)->aopu.aop_dir,
6757                AOP(left)->aopu.aop_dir);
6758       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6759                AOP(right)->aopu.aop_dir,
6760                AOP(right)->aopu.aop_dir);
6761       pic16_emitcode("setc","");
6762
6763     } else {
6764         tlbl = newiTempLabel(NULL);
6765         pic16_toBoolean(left);
6766         emitSKPZ;
6767         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6768         pic16_toBoolean(right);
6769         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6770
6771         pic16_outBitAcc(result);
6772     }
6773
6774     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6775     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6776     pic16_freeAsmop(result,NULL,ic,TRUE);            
6777 }
6778
6779 /*-----------------------------------------------------------------*/
6780 /* isLiteralBit - test if lit == 2^n                               */
6781 /*-----------------------------------------------------------------*/
6782 static int isLiteralBit(unsigned long lit)
6783 {
6784     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6785     0x100L,0x200L,0x400L,0x800L,
6786     0x1000L,0x2000L,0x4000L,0x8000L,
6787     0x10000L,0x20000L,0x40000L,0x80000L,
6788     0x100000L,0x200000L,0x400000L,0x800000L,
6789     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6790     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6791     int idx;
6792     
6793     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6794     for(idx = 0; idx < 32; idx++)
6795         if(lit == pw[idx])
6796             return idx+1;
6797     return 0;
6798 }
6799
6800 /*-----------------------------------------------------------------*/
6801 /* continueIfTrue -                                                */
6802 /*-----------------------------------------------------------------*/
6803 static void continueIfTrue (iCode *ic)
6804 {
6805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6806     if(IC_TRUE(ic))
6807         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6808     ic->generated = 1;
6809 }
6810
6811 /*-----------------------------------------------------------------*/
6812 /* jmpIfTrue -                                                     */
6813 /*-----------------------------------------------------------------*/
6814 static void jumpIfTrue (iCode *ic)
6815 {
6816     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6817     if(!IC_TRUE(ic))
6818         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6819     ic->generated = 1;
6820 }
6821
6822 /*-----------------------------------------------------------------*/
6823 /* jmpTrueOrFalse -                                                */
6824 /*-----------------------------------------------------------------*/
6825 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6826 {
6827     // ugly but optimized by peephole
6828     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6829     if(IC_TRUE(ic)){
6830         symbol *nlbl = newiTempLabel(NULL);
6831         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6832         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6833         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6834         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6835     }
6836     else{
6837         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6838         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6839     }
6840     ic->generated = 1;
6841 }
6842
6843 /*-----------------------------------------------------------------*/
6844 /* genAnd  - code for and                                          */
6845 /*-----------------------------------------------------------------*/
6846 static void genAnd (iCode *ic, iCode *ifx)
6847 {
6848   operand *left, *right, *result;
6849   int size, offset=0;  
6850   unsigned long lit = 0L;
6851   int bytelit = 0;
6852   resolvedIfx rIfx;
6853
6854
6855   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6856   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6857   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6858   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6859
6860   resolveIfx(&rIfx,ifx);
6861
6862   /* if left is a literal & right is not then exchange them */
6863   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6864       AOP_NEEDSACC(left)) {
6865     operand *tmp = right ;
6866     right = left;
6867     left = tmp;
6868   }
6869
6870   /* if result = right then exchange them */
6871   if(pic16_sameRegs(AOP(result),AOP(right))){
6872     operand *tmp = right ;
6873     right = left;
6874     left = tmp;
6875   }
6876
6877   /* if right is bit then exchange them */
6878   if (AOP_TYPE(right) == AOP_CRY &&
6879       AOP_TYPE(left) != AOP_CRY){
6880     operand *tmp = right ;
6881     right = left;
6882     left = tmp;
6883   }
6884   if(AOP_TYPE(right) == AOP_LIT)
6885     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6886
6887   size = AOP_SIZE(result);
6888
6889   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6890
6891   // if(bit & yy)
6892   // result = bit & yy;
6893   if (AOP_TYPE(left) == AOP_CRY){
6894     // c = bit & literal;
6895     if(AOP_TYPE(right) == AOP_LIT){
6896       if(lit & 1) {
6897         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6898           // no change
6899           goto release;
6900         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6901       } else {
6902         // bit(result) = 0;
6903         if(size && (AOP_TYPE(result) == AOP_CRY)){
6904           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6905           goto release;
6906         }
6907         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6908           jumpIfTrue(ifx);
6909           goto release;
6910         }
6911         pic16_emitcode("clr","c");
6912       }
6913     } else {
6914       if (AOP_TYPE(right) == AOP_CRY){
6915         // c = bit & bit;
6916         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6917         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6918       } else {
6919         // c = bit & val;
6920         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6921         // c = lsb
6922         pic16_emitcode("rrc","a");
6923         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6924       }
6925     }
6926     // bit = c
6927     // val = c
6928     if(size)
6929       pic16_outBitC(result);
6930     // if(bit & ...)
6931     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6932       genIfxJump(ifx, "c");           
6933     goto release ;
6934   }
6935
6936   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6937   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6938   if((AOP_TYPE(right) == AOP_LIT) &&
6939      (AOP_TYPE(result) == AOP_CRY) &&
6940      (AOP_TYPE(left) != AOP_CRY)){
6941     int posbit = isLiteralBit(lit);
6942     /* left &  2^n */
6943     if(posbit){
6944       posbit--;
6945       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6946       // bit = left & 2^n
6947       if(size)
6948         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6949       // if(left &  2^n)
6950       else{
6951         if(ifx){
6952 /*
6953           if(IC_TRUE(ifx)) {
6954             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6955             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6956           } else {
6957             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6958             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6959           }
6960 */
6961         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6962         size = AOP_SIZE(left);
6963
6964         {
6965           int bp = posbit, ofs=0;
6966           
6967             while(bp > 7) {
6968               bp -= 8;
6969               ofs++;
6970             }
6971         
6972           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6973                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6974
6975         }
6976 /*
6977           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6978                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6979 */
6980           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6981           
6982           ifx->generated = 1;
6983         }
6984         goto release;
6985       }
6986     } else {
6987       symbol *tlbl = newiTempLabel(NULL);
6988       int sizel = AOP_SIZE(left);
6989
6990       if(size)
6991         emitSETC;
6992
6993       while(sizel--) {
6994         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6995
6996           /* patch provided by Aaron Colwell */
6997           if((posbit = isLiteralBit(bytelit)) != 0) {
6998               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6999                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7000                                                 (posbit-1),0, PO_GPR_REGISTER));
7001
7002               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7003 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7004           } else {
7005               if (bytelit == 0xff) {
7006                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7007                    * a peephole could optimize it out -- VR */
7008                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7009               } else {
7010                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7011                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7012               }
7013
7014               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7015                             pic16_popGetLabel(tlbl->key));
7016           }
7017         
7018 #if 0
7019           /* old code, left here for reference -- VR 09/2004 */
7020           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7021           // byte ==  2^n ?
7022           if((posbit = isLiteralBit(bytelit)) != 0)
7023             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7024           else{
7025             if(bytelit != 0x0FFL)
7026               pic16_emitcode("anl","a,%s",
7027                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7028             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7029           }
7030 #endif
7031         }
7032         offset++;
7033       }
7034       // bit = left & literal
7035       if(size) {
7036         emitCLRC;
7037         pic16_emitpLabel(tlbl->key);
7038       }
7039       // if(left & literal)
7040       else {
7041         if(ifx) {
7042           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7043           pic16_emitpLabel(tlbl->key);
7044           ifx->generated = 1;
7045         }
7046         goto release;
7047       }
7048     }
7049
7050     pic16_outBitC(result);
7051     goto release ;
7052   }
7053
7054   /* if left is same as result */
7055   if(pic16_sameRegs(AOP(result),AOP(left))){
7056     int know_W = -1;
7057     for(;size--; offset++,lit>>=8) {
7058       if(AOP_TYPE(right) == AOP_LIT){
7059         switch(lit & 0xff) {
7060         case 0x00:
7061           /*  and'ing with 0 has clears the result */
7062 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7063           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7064           break;
7065         case 0xff:
7066           /* and'ing with 0xff is a nop when the result and left are the same */
7067           break;
7068
7069         default:
7070           {
7071             int p = my_powof2( (~lit) & 0xff );
7072             if(p>=0) {
7073               /* only one bit is set in the literal, so use a bcf instruction */
7074 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7075               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7076
7077             } else {
7078               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7079               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7080               if(know_W != (lit&0xff))
7081                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7082               know_W = lit &0xff;
7083               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7084             }
7085           }    
7086         }
7087       } else {
7088         if (AOP_TYPE(left) == AOP_ACC) {
7089           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7090         } else {                    
7091           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7092           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7093
7094         }
7095       }
7096     }
7097
7098   } else {
7099     // left & result in different registers
7100     if(AOP_TYPE(result) == AOP_CRY){
7101       // result = bit
7102       // if(size), result in bit
7103       // if(!size && ifx), conditional oper: if(left & right)
7104       symbol *tlbl = newiTempLabel(NULL);
7105       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7106       if(size)
7107         pic16_emitcode("setb","c");
7108       while(sizer--){
7109         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7110         pic16_emitcode("anl","a,%s",
7111                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7112         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7113         offset++;
7114       }
7115       if(size){
7116         CLRC;
7117         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7118         pic16_outBitC(result);
7119       } else if(ifx)
7120         jmpTrueOrFalse(ifx, tlbl);
7121     } else {
7122       for(;(size--);offset++) {
7123         // normal case
7124         // result = left & right
7125         if(AOP_TYPE(right) == AOP_LIT){
7126           int t = (lit >> (offset*8)) & 0x0FFL;
7127           switch(t) { 
7128           case 0x00:
7129             pic16_emitcode("clrf","%s",
7130                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7131             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7132             break;
7133           case 0xff:
7134             pic16_emitcode("movf","%s,w",
7135                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7136             pic16_emitcode("movwf","%s",
7137                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7138             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7139             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7140             break;
7141           default:
7142             pic16_emitcode("movlw","0x%x",t);
7143             pic16_emitcode("andwf","%s,w",
7144                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7145             pic16_emitcode("movwf","%s",
7146                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7147               
7148             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7149             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7150             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7151           }
7152           continue;
7153         }
7154
7155         if (AOP_TYPE(left) == AOP_ACC) {
7156           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7157           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7158         } else {
7159           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7160           pic16_emitcode("andwf","%s,w",
7161                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7162           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7163           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7164         }
7165         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7166         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7167       }
7168     }
7169   }
7170
7171   release :
7172     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7173   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7174   pic16_freeAsmop(result,NULL,ic,TRUE);     
7175 }
7176
7177 /*-----------------------------------------------------------------*/
7178 /* genOr  - code for or                                            */
7179 /*-----------------------------------------------------------------*/
7180 static void genOr (iCode *ic, iCode *ifx)
7181 {
7182     operand *left, *right, *result;
7183     int size, offset=0;
7184     unsigned long lit = 0L;
7185
7186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7187
7188     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7189     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7190     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7191
7192     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7193
7194     /* if left is a literal & right is not then exchange them */
7195     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7196         AOP_NEEDSACC(left)) {
7197         operand *tmp = right ;
7198         right = left;
7199         left = tmp;
7200     }
7201
7202     /* if result = right then exchange them */
7203     if(pic16_sameRegs(AOP(result),AOP(right))){
7204         operand *tmp = right ;
7205         right = left;
7206         left = tmp;
7207     }
7208
7209     /* if right is bit then exchange them */
7210     if (AOP_TYPE(right) == AOP_CRY &&
7211         AOP_TYPE(left) != AOP_CRY){
7212         operand *tmp = right ;
7213         right = left;
7214         left = tmp;
7215     }
7216
7217     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7218
7219     if(AOP_TYPE(right) == AOP_LIT)
7220         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7221
7222     size = AOP_SIZE(result);
7223
7224     // if(bit | yy)
7225     // xx = bit | yy;
7226     if (AOP_TYPE(left) == AOP_CRY){
7227         if(AOP_TYPE(right) == AOP_LIT){
7228             // c = bit & literal;
7229             if(lit){
7230                 // lit != 0 => result = 1
7231                 if(AOP_TYPE(result) == AOP_CRY){
7232                   if(size)
7233                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7234                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7235                   //     AOP(result)->aopu.aop_dir,
7236                   //     AOP(result)->aopu.aop_dir);
7237                     else if(ifx)
7238                         continueIfTrue(ifx);
7239                     goto release;
7240                 }
7241             } else {
7242                 // lit == 0 => result = left
7243                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7244                     goto release;
7245                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7246             }
7247         } else {
7248             if (AOP_TYPE(right) == AOP_CRY){
7249               if(pic16_sameRegs(AOP(result),AOP(left))){
7250                 // c = bit | bit;
7251                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7252                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7253                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7254
7255                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7256                          AOP(result)->aopu.aop_dir,
7257                          AOP(result)->aopu.aop_dir);
7258                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7259                          AOP(right)->aopu.aop_dir,
7260                          AOP(right)->aopu.aop_dir);
7261                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7262                          AOP(result)->aopu.aop_dir,
7263                          AOP(result)->aopu.aop_dir);
7264               } else {
7265                 if( AOP_TYPE(result) == AOP_ACC) {
7266                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7267                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7268                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7269                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7270
7271                 } else {
7272
7273                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7274                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7275                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7276                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7277
7278                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7279                                  AOP(result)->aopu.aop_dir,
7280                                  AOP(result)->aopu.aop_dir);
7281                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7282                                  AOP(right)->aopu.aop_dir,
7283                                  AOP(right)->aopu.aop_dir);
7284                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7285                                  AOP(left)->aopu.aop_dir,
7286                                  AOP(left)->aopu.aop_dir);
7287                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7288                                  AOP(result)->aopu.aop_dir,
7289                                  AOP(result)->aopu.aop_dir);
7290                 }
7291               }
7292             } else {
7293                 // c = bit | val;
7294                 symbol *tlbl = newiTempLabel(NULL);
7295                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7296
7297
7298                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7299                 if( AOP_TYPE(right) == AOP_ACC) {
7300                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7301                   emitSKPNZ;
7302                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7303                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7304                 }
7305
7306
7307
7308                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7309                     pic16_emitcode(";XXX setb","c");
7310                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7311                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7312                 pic16_toBoolean(right);
7313                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7314                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7315                     jmpTrueOrFalse(ifx, tlbl);
7316                     goto release;
7317                 } else {
7318                     CLRC;
7319                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7320                 }
7321             }
7322         }
7323         // bit = c
7324         // val = c
7325         if(size)
7326             pic16_outBitC(result);
7327         // if(bit | ...)
7328         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7329             genIfxJump(ifx, "c");           
7330         goto release ;
7331     }
7332
7333     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7334     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7335     if((AOP_TYPE(right) == AOP_LIT) &&
7336        (AOP_TYPE(result) == AOP_CRY) &&
7337        (AOP_TYPE(left) != AOP_CRY)){
7338         if(lit){
7339           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7340             // result = 1
7341             if(size)
7342                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7343             else 
7344                 continueIfTrue(ifx);
7345             goto release;
7346         } else {
7347           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7348             // lit = 0, result = boolean(left)
7349             if(size)
7350                 pic16_emitcode(";XXX setb","c");
7351             pic16_toBoolean(right);
7352             if(size){
7353                 symbol *tlbl = newiTempLabel(NULL);
7354                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7355                 CLRC;
7356                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7357             } else {
7358                 genIfxJump (ifx,"a");
7359                 goto release;
7360             }
7361         }
7362         pic16_outBitC(result);
7363         goto release ;
7364     }
7365
7366     /* if left is same as result */
7367     if(pic16_sameRegs(AOP(result),AOP(left))){
7368       int know_W = -1;
7369       for(;size--; offset++,lit>>=8) {
7370         if(AOP_TYPE(right) == AOP_LIT){
7371           if((lit & 0xff) == 0)
7372             /*  or'ing with 0 has no effect */
7373             continue;
7374           else {
7375             int p = my_powof2(lit & 0xff);
7376             if(p>=0) {
7377               /* only one bit is set in the literal, so use a bsf instruction */
7378               pic16_emitpcode(POC_BSF,
7379                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7380             } else {
7381               if(know_W != (lit & 0xff))
7382                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7383               know_W = lit & 0xff;
7384               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7385             }
7386                     
7387           }
7388         } else {
7389           if (AOP_TYPE(left) == AOP_ACC) {
7390             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7391             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7392           } else {                  
7393             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7394             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7395
7396             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7397             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7398
7399           }
7400         }
7401       }
7402     } else {
7403         // left & result in different registers
7404         if(AOP_TYPE(result) == AOP_CRY){
7405             // result = bit
7406             // if(size), result in bit
7407             // if(!size && ifx), conditional oper: if(left | right)
7408             symbol *tlbl = newiTempLabel(NULL);
7409             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7410             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7411
7412
7413             if(size)
7414                 pic16_emitcode(";XXX setb","c");
7415             while(sizer--){
7416                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7417                 pic16_emitcode(";XXX orl","a,%s",
7418                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7419                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7420                 offset++;
7421             }
7422             if(size){
7423                 CLRC;
7424                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7425                 pic16_outBitC(result);
7426             } else if(ifx)
7427                 jmpTrueOrFalse(ifx, tlbl);
7428         } else for(;(size--);offset++){
7429           // normal case
7430           // result = left & right
7431           if(AOP_TYPE(right) == AOP_LIT){
7432             int t = (lit >> (offset*8)) & 0x0FFL;
7433             switch(t) { 
7434             case 0x00:
7435               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7436               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7437
7438               pic16_emitcode("movf","%s,w",
7439                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7440               pic16_emitcode("movwf","%s",
7441                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7442               break;
7443             default:
7444               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7445               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7446               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7447
7448               pic16_emitcode("movlw","0x%x",t);
7449               pic16_emitcode("iorwf","%s,w",
7450                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7451               pic16_emitcode("movwf","%s",
7452                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7453               
7454             }
7455             continue;
7456           }
7457
7458           // faster than result <- left, anl result,right
7459           // and better if result is SFR
7460           if (AOP_TYPE(left) == AOP_ACC) {
7461             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7462             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7463           } else {
7464             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7465             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7466
7467             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7468             pic16_emitcode("iorwf","%s,w",
7469                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7470           }
7471           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7472           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7473         }
7474     }
7475
7476 release :
7477     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7478     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7479     pic16_freeAsmop(result,NULL,ic,TRUE);     
7480 }
7481
7482 /*-----------------------------------------------------------------*/
7483 /* genXor - code for xclusive or                                   */
7484 /*-----------------------------------------------------------------*/
7485 static void genXor (iCode *ic, iCode *ifx)
7486 {
7487   operand *left, *right, *result;
7488   int size, offset=0;
7489   unsigned long lit = 0L;
7490
7491   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7492
7493   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7494   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7495   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7496
7497   /* if left is a literal & right is not ||
7498      if left needs acc & right does not */
7499   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7500       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7501     operand *tmp = right ;
7502     right = left;
7503     left = tmp;
7504   }
7505
7506   /* if result = right then exchange them */
7507   if(pic16_sameRegs(AOP(result),AOP(right))){
7508     operand *tmp = right ;
7509     right = left;
7510     left = tmp;
7511   }
7512
7513   /* if right is bit then exchange them */
7514   if (AOP_TYPE(right) == AOP_CRY &&
7515       AOP_TYPE(left) != AOP_CRY){
7516     operand *tmp = right ;
7517     right = left;
7518     left = tmp;
7519   }
7520   if(AOP_TYPE(right) == AOP_LIT)
7521     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7522
7523   size = AOP_SIZE(result);
7524
7525   // if(bit ^ yy)
7526   // xx = bit ^ yy;
7527   if (AOP_TYPE(left) == AOP_CRY){
7528     if(AOP_TYPE(right) == AOP_LIT){
7529       // c = bit & literal;
7530       if(lit>>1){
7531         // lit>>1  != 0 => result = 1
7532         if(AOP_TYPE(result) == AOP_CRY){
7533           if(size)
7534             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7535             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7536           else if(ifx)
7537             continueIfTrue(ifx);
7538           goto release;
7539         }
7540         pic16_emitcode("setb","c");
7541       } else{
7542         // lit == (0 or 1)
7543         if(lit == 0){
7544           // lit == 0, result = left
7545           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7546             goto release;
7547           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7548         } else{
7549           // lit == 1, result = not(left)
7550           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7551             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7552             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7553             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7554             goto release;
7555           } else {
7556             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7557             pic16_emitcode("cpl","c");
7558           }
7559         }
7560       }
7561
7562     } else {
7563       // right != literal
7564       symbol *tlbl = newiTempLabel(NULL);
7565       if (AOP_TYPE(right) == AOP_CRY){
7566         // c = bit ^ bit;
7567         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7568       }
7569       else{
7570         int sizer = AOP_SIZE(right);
7571         // c = bit ^ val
7572         // if val>>1 != 0, result = 1
7573         pic16_emitcode("setb","c");
7574         while(sizer){
7575           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7576           if(sizer == 1)
7577             // test the msb of the lsb
7578             pic16_emitcode("anl","a,#0xfe");
7579           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7580           sizer--;
7581         }
7582         // val = (0,1)
7583         pic16_emitcode("rrc","a");
7584       }
7585       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7586       pic16_emitcode("cpl","c");
7587       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7588     }
7589     // bit = c
7590     // val = c
7591     if(size)
7592       pic16_outBitC(result);
7593     // if(bit | ...)
7594     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7595       genIfxJump(ifx, "c");           
7596     goto release ;
7597   }
7598
7599   if(pic16_sameRegs(AOP(result),AOP(left))){
7600     /* if left is same as result */
7601     for(;size--; offset++) {
7602       if(AOP_TYPE(right) == AOP_LIT){
7603         int t  = (lit >> (offset*8)) & 0x0FFL;
7604         if(t == 0x00L)
7605           continue;
7606         else
7607           if (IS_AOP_PREG(left)) {
7608             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7609             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7610             pic16_aopPut(AOP(result),"a",offset);
7611           } else {
7612             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7613             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7614             pic16_emitcode("xrl","%s,%s",
7615                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7616                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7617           }
7618       } else {
7619         if (AOP_TYPE(left) == AOP_ACC)
7620           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7621         else {
7622           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7623           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7624 /*
7625           if (IS_AOP_PREG(left)) {
7626             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7627             pic16_aopPut(AOP(result),"a",offset);
7628           } else
7629             pic16_emitcode("xrl","%s,a",
7630                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7631 */
7632         }
7633       }
7634     }
7635   } else {
7636     // left & result in different registers
7637     if(AOP_TYPE(result) == AOP_CRY){
7638       // result = bit
7639       // if(size), result in bit
7640       // if(!size && ifx), conditional oper: if(left ^ right)
7641       symbol *tlbl = newiTempLabel(NULL);
7642       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7643       if(size)
7644         pic16_emitcode("setb","c");
7645       while(sizer--){
7646         if((AOP_TYPE(right) == AOP_LIT) &&
7647            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7648           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7649         } else {
7650           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7651           pic16_emitcode("xrl","a,%s",
7652                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7653         }
7654         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7655         offset++;
7656       }
7657       if(size){
7658         CLRC;
7659         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7660         pic16_outBitC(result);
7661       } else if(ifx)
7662         jmpTrueOrFalse(ifx, tlbl);
7663     } else for(;(size--);offset++){
7664       // normal case
7665       // result = left & right
7666       if(AOP_TYPE(right) == AOP_LIT){
7667         int t = (lit >> (offset*8)) & 0x0FFL;
7668         switch(t) { 
7669         case 0x00:
7670           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7671           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7672           pic16_emitcode("movf","%s,w",
7673                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7674           pic16_emitcode("movwf","%s",
7675                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7676           break;
7677         case 0xff:
7678           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7679           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7680           pic16_emitcode("comf","%s,w",
7681                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7682           pic16_emitcode("movwf","%s",
7683                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7684           break;
7685         default:
7686           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7687           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7688           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7689           pic16_emitcode("movlw","0x%x",t);
7690           pic16_emitcode("xorwf","%s,w",
7691                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7692           pic16_emitcode("movwf","%s",
7693                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7694
7695         }
7696         continue;
7697       }
7698
7699       // faster than result <- left, anl result,right
7700       // and better if result is SFR
7701       if (AOP_TYPE(left) == AOP_ACC) {
7702         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7703         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7704       } else {
7705         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7706         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7707         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7708         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7709       }
7710       if ( AOP_TYPE(result) != AOP_ACC){
7711         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7712         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7713       }
7714     }
7715   }
7716
7717   release :
7718     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7719   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7720   pic16_freeAsmop(result,NULL,ic,TRUE);     
7721 }
7722
7723 /*-----------------------------------------------------------------*/
7724 /* genInline - write the inline code out                           */
7725 /*-----------------------------------------------------------------*/
7726 static void genInline (iCode *ic)
7727 {
7728   char *buffer, *bp, *bp1;
7729     
7730         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7731
7732         _G.inLine += (!options.asmpeep);
7733
7734         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7735         strcpy(buffer,IC_INLINE(ic));
7736
7737 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7738
7739         /* emit each line as a code */
7740         while (*bp) {
7741                 if (*bp == '\n') {
7742                         *bp++ = '\0';
7743
7744                         if(*bp1)
7745                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7746                         bp1 = bp;
7747                 } else {
7748                         if (*bp == ':') {
7749                                 bp++;
7750                                 *bp = '\0';
7751                                 bp++;
7752
7753                                 /* print label, use this special format with NULL directive
7754                                  * to denote that the argument should not be indented with tab */
7755                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7756                                 bp1 = bp;
7757                         } else
7758                                 bp++;
7759                 }
7760         }
7761
7762         if ((bp1 != bp) && *bp1)
7763                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7764
7765
7766     Safe_free(buffer);
7767
7768     _G.inLine -= (!options.asmpeep);
7769 }
7770
7771 /*-----------------------------------------------------------------*/
7772 /* genRRC - rotate right with carry                                */
7773 /*-----------------------------------------------------------------*/
7774 static void genRRC (iCode *ic)
7775 {
7776   operand *left , *result ;
7777   int size, offset = 0, same;
7778
7779   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7780
7781   /* rotate right with carry */
7782   left = IC_LEFT(ic);
7783   result=IC_RESULT(ic);
7784   pic16_aopOp (left,ic,FALSE);
7785   pic16_aopOp (result,ic,FALSE);
7786
7787   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7788
7789   same = pic16_sameRegs(AOP(result),AOP(left));
7790
7791   size = AOP_SIZE(result);    
7792
7793   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7794
7795   /* get the lsb and put it into the carry */
7796   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7797
7798   offset = 0 ;
7799
7800   while(size--) {
7801
7802     if(same) {
7803       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7804     } else {
7805       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7806       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7807     }
7808
7809     offset++;
7810   }
7811
7812   pic16_freeAsmop(left,NULL,ic,TRUE);
7813   pic16_freeAsmop(result,NULL,ic,TRUE);
7814 }
7815
7816 /*-----------------------------------------------------------------*/
7817 /* genRLC - generate code for rotate left with carry               */
7818 /*-----------------------------------------------------------------*/
7819 static void genRLC (iCode *ic)
7820 {    
7821   operand *left , *result ;
7822   int size, offset = 0;
7823   int same;
7824
7825   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7826   /* rotate right with carry */
7827   left = IC_LEFT(ic);
7828   result=IC_RESULT(ic);
7829   pic16_aopOp (left,ic,FALSE);
7830   pic16_aopOp (result,ic,FALSE);
7831
7832   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7833
7834   same = pic16_sameRegs(AOP(result),AOP(left));
7835
7836   /* move it to the result */
7837   size = AOP_SIZE(result);    
7838
7839   /* get the msb and put it into the carry */
7840   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7841
7842   offset = 0 ;
7843
7844   while(size--) {
7845
7846     if(same) {
7847       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7848     } else {
7849       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7850       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7851     }
7852
7853     offset++;
7854   }
7855
7856
7857   pic16_freeAsmop(left,NULL,ic,TRUE);
7858   pic16_freeAsmop(result,NULL,ic,TRUE);
7859 }
7860
7861
7862 /* gpasm can get the highest order bit with HIGH/UPPER
7863  * so the following probably is not needed -- VR */
7864  
7865 /*-----------------------------------------------------------------*/
7866 /* genGetHbit - generates code get highest order bit               */
7867 /*-----------------------------------------------------------------*/
7868 static void genGetHbit (iCode *ic)
7869 {
7870     operand *left, *result;
7871     left = IC_LEFT(ic);
7872     result=IC_RESULT(ic);
7873     pic16_aopOp (left,ic,FALSE);
7874     pic16_aopOp (result,ic,FALSE);
7875
7876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7877     /* get the highest order byte into a */
7878     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7879     if(AOP_TYPE(result) == AOP_CRY){
7880         pic16_emitcode("rlc","a");
7881         pic16_outBitC(result);
7882     }
7883     else{
7884         pic16_emitcode("rl","a");
7885         pic16_emitcode("anl","a,#0x01");
7886         pic16_outAcc(result);
7887     }
7888
7889
7890     pic16_freeAsmop(left,NULL,ic,TRUE);
7891     pic16_freeAsmop(result,NULL,ic,TRUE);
7892 }
7893
7894 #if 0
7895 /*-----------------------------------------------------------------*/
7896 /* AccRol - rotate left accumulator by known count                 */
7897 /*-----------------------------------------------------------------*/
7898 static void AccRol (int shCount)
7899 {
7900     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7901     shCount &= 0x0007;              // shCount : 0..7
7902     switch(shCount){
7903         case 0 :
7904             break;
7905         case 1 :
7906             pic16_emitcode("rl","a");
7907             break;
7908         case 2 :
7909             pic16_emitcode("rl","a");
7910             pic16_emitcode("rl","a");
7911             break;
7912         case 3 :
7913             pic16_emitcode("swap","a");
7914             pic16_emitcode("rr","a");
7915             break;
7916         case 4 :
7917             pic16_emitcode("swap","a");
7918             break;
7919         case 5 :
7920             pic16_emitcode("swap","a");
7921             pic16_emitcode("rl","a");
7922             break;
7923         case 6 :
7924             pic16_emitcode("rr","a");
7925             pic16_emitcode("rr","a");
7926             break;
7927         case 7 :
7928             pic16_emitcode("rr","a");
7929             break;
7930     }
7931 }
7932 #endif
7933
7934 /*-----------------------------------------------------------------*/
7935 /* AccLsh - left shift accumulator by known count                  */
7936 /*-----------------------------------------------------------------*/
7937 static void AccLsh (int shCount)
7938 {
7939         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940         switch(shCount){
7941                 case 0 :
7942                         return;
7943                         break;
7944                 case 1 :
7945                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7946                         break;
7947                 case 2 :
7948                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7949                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7950                         break;
7951                 case 3 :
7952                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7953                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7954                         break;
7955                 case 4 :
7956                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7957                         break;
7958                 case 5 :
7959                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7960                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7961                         break;
7962                 case 6 :
7963                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7964                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7965                         break;
7966                 case 7 :
7967                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7968                         break;
7969         }
7970
7971         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7972 }
7973
7974 /*-----------------------------------------------------------------*/
7975 /* AccRsh - right shift accumulator by known count                 */
7976 /*-----------------------------------------------------------------*/
7977 static void AccRsh (int shCount, int andmask)
7978 {
7979         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7980         switch(shCount){
7981                 case 0 :
7982                         return; break;
7983                 case 1 :
7984                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7985                         break;
7986                 case 2 :
7987                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7988                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7989                         break;
7990                 case 3 :
7991                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7992                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7993                         break;
7994                 case 4 :
7995                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7996                         break;
7997                 case 5 :
7998                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7999                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8000                         break;
8001                 case 6 :
8002                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8003                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8004                         break;
8005                 case 7 :
8006                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8007                         break;
8008         }
8009         
8010         if(andmask)
8011                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8012         else
8013                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8014 }
8015
8016 #if 0
8017 /*-----------------------------------------------------------------*/
8018 /* AccSRsh - signed right shift accumulator by known count                 */
8019 /*-----------------------------------------------------------------*/
8020 static void AccSRsh (int shCount)
8021 {
8022     symbol *tlbl ;
8023     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8024     if(shCount != 0){
8025         if(shCount == 1){
8026             pic16_emitcode("mov","c,acc.7");
8027             pic16_emitcode("rrc","a");
8028         } else if(shCount == 2){
8029             pic16_emitcode("mov","c,acc.7");
8030             pic16_emitcode("rrc","a");
8031             pic16_emitcode("mov","c,acc.7");
8032             pic16_emitcode("rrc","a");
8033         } else {
8034             tlbl = newiTempLabel(NULL);
8035             /* rotate right accumulator */
8036             AccRol(8 - shCount);
8037             /* and kill the higher order bits */
8038             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8039             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8040             pic16_emitcode("orl","a,#0x%02x",
8041                      (unsigned char)~SRMask[shCount]);
8042             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8043         }
8044     }
8045 }
8046 #endif
8047
8048 /*-----------------------------------------------------------------*/
8049 /* shiftR1Left2Result - shift right one byte from left to result   */
8050 /*-----------------------------------------------------------------*/
8051 static void shiftR1Left2ResultSigned (operand *left, int offl,
8052                                 operand *result, int offr,
8053                                 int shCount)
8054 {
8055   int same;
8056
8057   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8058
8059   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8060
8061   switch(shCount) {
8062   case 1:
8063     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8064     if(same) 
8065       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8066     else {
8067       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8068       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8069     }
8070
8071     break;
8072   case 2:
8073
8074     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8075     if(same) 
8076       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8077     else {
8078       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8079       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8080     }
8081     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8082     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8083
8084     break;
8085
8086   case 3:
8087     if(same)
8088       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8089     else {
8090       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8091       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8092     }
8093
8094     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8095     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8096     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8097
8098     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8099     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8100
8101     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8102     break;
8103
8104   case 4:
8105     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8106     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8107     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8108     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8109     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8110     break;
8111   case 5:
8112     if(same) {
8113       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8114     } else {
8115       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8116       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8117     }
8118     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8119     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8120     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8121     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8122     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8123     break;
8124
8125   case 6:
8126     if(same) {
8127       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8128       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8129       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8130       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8131       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8132       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8133     } else {
8134       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8135       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8136       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8137       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8138       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8139     }
8140     break;
8141
8142   case 7:
8143     if(same) {
8144       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8145       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8146       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8147       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8148     } else {
8149       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8150       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8151       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8152     }
8153
8154   default:
8155     break;
8156   }
8157 }
8158
8159 /*-----------------------------------------------------------------*/
8160 /* shiftR1Left2Result - shift right one byte from left to result   */
8161 /*-----------------------------------------------------------------*/
8162 static void shiftR1Left2Result (operand *left, int offl,
8163                                 operand *result, int offr,
8164                                 int shCount, int sign)
8165 {
8166   int same;
8167
8168   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8169
8170   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8171
8172   /* Copy the msb into the carry if signed. */
8173   if(sign) {
8174     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8175     return;
8176   }
8177
8178
8179
8180   switch(shCount) {
8181   case 1:
8182     emitCLRC;
8183     if(same) 
8184       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8185     else {
8186       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8187       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8188     }
8189     break;
8190   case 2:
8191     emitCLRC;
8192     if(same) {
8193       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8194     } else {
8195       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8196       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8197     }
8198     emitCLRC;
8199     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8200
8201     break;
8202   case 3:
8203     if(same)
8204       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8205     else {
8206       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8207       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8208     }
8209
8210     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8211     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8212     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8213     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8214     break;
8215       
8216   case 4:
8217     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8218     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8219     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8220     break;
8221
8222   case 5:
8223     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8224     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8225     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8226     //emitCLRC;
8227     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8228
8229     break;
8230   case 6:
8231
8232     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8233     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8234     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8235     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8236     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8237     break;
8238
8239   case 7:
8240
8241     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8242     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8243     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8244
8245     break;
8246
8247   default:
8248     break;
8249   }
8250 }
8251
8252 /*-----------------------------------------------------------------*/
8253 /* shiftL1Left2Result - shift left one byte from left to result    */
8254 /*-----------------------------------------------------------------*/
8255 static void shiftL1Left2Result (operand *left, int offl,
8256                                 operand *result, int offr, int shCount)
8257 {
8258   int same;
8259
8260   //    char *l;
8261   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8262
8263   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8264   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8265     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8266     //    MOVA(l);
8267     /* shift left accumulator */
8268     //AccLsh(shCount); // don't comment out just yet...
8269   //    pic16_aopPut(AOP(result),"a",offr);
8270
8271   switch(shCount) {
8272   case 1:
8273     /* Shift left 1 bit position */
8274     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8275     if(same) {
8276       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8277     } else {
8278       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8280     }
8281     break;
8282   case 2:
8283     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8284     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8285     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8286     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8287     break;
8288   case 3:
8289     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8290     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8291     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8292     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8293     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8294     break;
8295   case 4:
8296     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8297     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8298     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8299     break;
8300   case 5:
8301     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8302     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8303     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8304     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8305     break;
8306   case 6:
8307     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8308     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8309     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8310     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8311     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8312     break;
8313   case 7:
8314     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8315     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8316     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8317     break;
8318
8319   default:
8320     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8321   }
8322
8323 }
8324
8325 /*-----------------------------------------------------------------*/
8326 /* movLeft2Result - move byte from left to result                  */
8327 /*-----------------------------------------------------------------*/
8328 static void movLeft2Result (operand *left, int offl,
8329                             operand *result, int offr)
8330 {
8331   char *l;
8332   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8333   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8334     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8335
8336     if (*l == '@' && (IS_AOP_PREG(result))) {
8337       pic16_emitcode("mov","a,%s",l);
8338       pic16_aopPut(AOP(result),"a",offr);
8339     } else {
8340       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8341       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8342     }
8343   }
8344 }
8345
8346 /*-----------------------------------------------------------------*/
8347 /* shiftL2Left2Result - shift left two bytes from left to result   */
8348 /*-----------------------------------------------------------------*/
8349 static void shiftL2Left2Result (operand *left, int offl,
8350                                 operand *result, int offr, int shCount)
8351 {
8352   int same = pic16_sameRegs(AOP(result), AOP(left));
8353   int i;
8354
8355   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8356
8357   if (same && (offl != offr)) { // shift bytes
8358     if (offr > offl) {
8359        for(i=1;i>-1;i--) {
8360          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8361          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8362        }
8363     } else { // just treat as different later on
8364                 same = 0;
8365     }
8366   }
8367
8368   if(same) {
8369     switch(shCount) {
8370     case 0:
8371       break;
8372     case 1:
8373     case 2:
8374     case 3:
8375
8376       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8377       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8378       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8379
8380       while(--shCount) {
8381                 emitCLRC;
8382                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8383                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8384       }
8385
8386       break;
8387     case 4:
8388     case 5:
8389       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8390       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8391       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8392       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8393       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8394       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8395       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8396       if(shCount >=5) {
8397                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8398                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8399       }
8400       break;
8401     case 6:
8402       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8403       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8404       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8405       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8406       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8407       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8408       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8409       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8410       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8411       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8412       break;
8413     case 7:
8414       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8415       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8416       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8417       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8418       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8419     }
8420
8421   } else {
8422     switch(shCount) {
8423     case 0:
8424       break;
8425     case 1:
8426     case 2:
8427     case 3:
8428       /* note, use a mov/add for the shift since the mov has a
8429          chance of getting optimized out */
8430       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8431       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8432       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8433       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8434       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8435
8436       while(--shCount) {
8437                 emitCLRC;
8438                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8439                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8440       }
8441       break;
8442
8443     case 4:
8444     case 5:
8445       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8446       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8447       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8448       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8449       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8450       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8451       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8452       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8453
8454
8455       if(shCount == 5) {
8456                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8457                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8458       }
8459       break;
8460     case 6:
8461       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8462       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8463       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8464       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8465
8466       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8467       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8468       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8469       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8470       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8471       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8472       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8473       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8474       break;
8475     case 7:
8476       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8477       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8478       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8479       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8480       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8481     }
8482   }
8483
8484 }
8485 /*-----------------------------------------------------------------*/
8486 /* shiftR2Left2Result - shift right two bytes from left to result  */
8487 /*-----------------------------------------------------------------*/
8488 static void shiftR2Left2Result (operand *left, int offl,
8489                                 operand *result, int offr,
8490                                 int shCount, int sign)
8491 {
8492   int same = pic16_sameRegs(AOP(result), AOP(left));
8493   int i;
8494   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8495
8496   if (same && (offl != offr)) { // shift right bytes
8497     if (offr < offl) {
8498        for(i=0;i<2;i++) {
8499          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8500          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8501        }
8502     } else { // just treat as different later on
8503                 same = 0;
8504     }
8505   }
8506
8507   switch(shCount) {
8508   case 0:
8509     break;
8510   case 1:
8511   case 2:
8512   case 3:
8513     if(sign)
8514       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8515     else
8516       emitCLRC;
8517
8518     if(same) {
8519       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8520       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8521     } else {
8522       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8523       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8524       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8525       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8526     }
8527
8528     while(--shCount) {
8529       if(sign)
8530                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8531       else
8532                 emitCLRC;
8533       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8534       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8535     }
8536     break;
8537   case 4:
8538   case 5:
8539     if(same) {
8540
8541       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8542       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8543       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8544
8545       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8546       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8547       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8548       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8549     } else {
8550       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8551       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8552       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8553
8554       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8555       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8556       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8557       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8558       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8559     }
8560
8561     if(shCount >=5) {
8562       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8563       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8564     }
8565
8566     if(sign) {
8567       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8568       pic16_emitpcode(POC_BTFSC, 
8569                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8570       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8571     }
8572
8573     break;
8574
8575   case 6:
8576     if(same) {
8577
8578       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8579       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8580
8581       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8582       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8583       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8584       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8585       if(sign) {
8586         pic16_emitpcode(POC_BTFSC, 
8587                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8588         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8589       }
8590       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8591       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8592       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8593       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8594     } else {
8595       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8596       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8597       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8598       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8599       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8600       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8601       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8602       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8603       if(sign) {
8604         pic16_emitpcode(POC_BTFSC, 
8605                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8606         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8607       }
8608       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8609       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8610
8611         
8612     }
8613
8614     break;
8615   case 7:
8616     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8617     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8618     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8619     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8620     if(sign) {
8621       emitSKPNC;
8622       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8623     } else 
8624       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8625   }
8626 }
8627
8628
8629 /*-----------------------------------------------------------------*/
8630 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8631 /*-----------------------------------------------------------------*/
8632 static void shiftLLeftOrResult (operand *left, int offl,
8633                                 operand *result, int offr, int shCount)
8634 {
8635     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8636
8637     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8638     /* shift left accumulator */
8639     AccLsh(shCount);
8640     /* or with result */
8641     /* back to result */
8642     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8643 }
8644
8645 /*-----------------------------------------------------------------*/
8646 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8647 /*-----------------------------------------------------------------*/
8648 static void shiftRLeftOrResult (operand *left, int offl,
8649                                 operand *result, int offr, int shCount)
8650 {
8651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8652     
8653     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8654     /* shift right accumulator */
8655     AccRsh(shCount, 1);
8656     /* or with result */
8657     /* back to result */
8658     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8659 }
8660
8661 /*-----------------------------------------------------------------*/
8662 /* genlshOne - left shift a one byte quantity by known count       */
8663 /*-----------------------------------------------------------------*/
8664 static void genlshOne (operand *result, operand *left, int shCount)
8665 {       
8666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8667     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8668 }
8669
8670 /*-----------------------------------------------------------------*/
8671 /* genlshTwo - left shift two bytes by known amount != 0           */
8672 /*-----------------------------------------------------------------*/
8673 static void genlshTwo (operand *result,operand *left, int shCount)
8674 {
8675     int size;
8676     
8677     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8678     size = pic16_getDataSize(result);
8679
8680     /* if shCount >= 8 */
8681     if (shCount >= 8) {
8682         shCount -= 8 ;
8683
8684         if (size > 1){
8685             if (shCount)
8686                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8687             else 
8688                 movLeft2Result(left, LSB, result, MSB16);
8689         }
8690         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8691     }
8692
8693     /*  1 <= shCount <= 7 */
8694     else {  
8695         if(size == 1)
8696             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8697         else 
8698             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8699     }
8700 }
8701
8702 /*-----------------------------------------------------------------*/
8703 /* shiftLLong - shift left one long from left to result            */
8704 /* offr = LSB or MSB16                                             */
8705 /*-----------------------------------------------------------------*/
8706 static void shiftLLong (operand *left, operand *result, int offr )
8707 {
8708     int size = AOP_SIZE(result);
8709     int same = pic16_sameRegs(AOP(left),AOP(result));
8710         int i;
8711
8712     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8713
8714         if (same && (offr == MSB16)) { //shift one byte
8715                 for(i=size-1;i>=MSB16;i--) {
8716                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8717                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8718                 }
8719         } else {
8720                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8721         }
8722         
8723     if (size > LSB+offr ){
8724                 if (same) {
8725                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8726                 } else {
8727                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8728                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8729                 }
8730          }
8731
8732     if(size > MSB16+offr){
8733                 if (same) {
8734                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8735                 } else {
8736                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8737                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8738                 }
8739     }
8740
8741     if(size > MSB24+offr){
8742                 if (same) {
8743                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8744                 } else {
8745                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8746                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8747                 }
8748     }
8749
8750     if(size > MSB32+offr){
8751                 if (same) {
8752                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8753                 } else {
8754                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8755                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8756                 }
8757     }
8758     if(offr != LSB)
8759                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8760
8761 }
8762
8763 /*-----------------------------------------------------------------*/
8764 /* genlshFour - shift four byte by a known amount != 0             */
8765 /*-----------------------------------------------------------------*/
8766 static void genlshFour (operand *result, operand *left, int shCount)
8767 {
8768     int size;
8769
8770     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8771     size = AOP_SIZE(result);
8772
8773     /* if shifting more that 3 bytes */
8774     if (shCount >= 24 ) {
8775         shCount -= 24;
8776         if (shCount)
8777             /* lowest order of left goes to the highest
8778             order of the destination */
8779             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8780         else
8781             movLeft2Result(left, LSB, result, MSB32);
8782
8783                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8784                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8785                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8786
8787         return;
8788     }
8789
8790     /* more than two bytes */
8791     else if ( shCount >= 16 ) {
8792         /* lower order two bytes goes to higher order two bytes */
8793         shCount -= 16;
8794         /* if some more remaining */
8795         if (shCount)
8796             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8797         else {
8798             movLeft2Result(left, MSB16, result, MSB32);
8799             movLeft2Result(left, LSB, result, MSB24);
8800         }
8801                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8802                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8803         return;
8804     }    
8805
8806     /* if more than 1 byte */
8807     else if ( shCount >= 8 ) {
8808         /* lower order three bytes goes to higher order  three bytes */
8809         shCount -= 8;
8810         if(size == 2){
8811             if(shCount)
8812                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8813             else
8814                 movLeft2Result(left, LSB, result, MSB16);
8815         }
8816         else{   /* size = 4 */
8817             if(shCount == 0){
8818                 movLeft2Result(left, MSB24, result, MSB32);
8819                 movLeft2Result(left, MSB16, result, MSB24);
8820                 movLeft2Result(left, LSB, result, MSB16);
8821                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8822             }
8823             else if(shCount == 1)
8824                 shiftLLong(left, result, MSB16);
8825             else{
8826                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8827                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8828                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8829                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8830             }
8831         }
8832     }
8833
8834     /* 1 <= shCount <= 7 */
8835     else if(shCount <= 3)
8836     { 
8837         shiftLLong(left, result, LSB);
8838         while(--shCount >= 1)
8839             shiftLLong(result, result, LSB);
8840     }
8841     /* 3 <= shCount <= 7, optimize */
8842     else{
8843         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8844         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8845         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8846     }
8847 }
8848
8849 /*-----------------------------------------------------------------*/
8850 /* genLeftShiftLiteral - left shifting by known count              */
8851 /*-----------------------------------------------------------------*/
8852 static void genLeftShiftLiteral (operand *left,
8853                                  operand *right,
8854                                  operand *result,
8855                                  iCode *ic)
8856 {    
8857     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8858     int size;
8859
8860     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8861     pic16_freeAsmop(right,NULL,ic,TRUE);
8862
8863     pic16_aopOp(left,ic,FALSE);
8864     pic16_aopOp(result,ic,FALSE);
8865
8866     size = getSize(operandType(result));
8867
8868 #if VIEW_SIZE
8869     pic16_emitcode("; shift left ","result %d, left %d",size,
8870              AOP_SIZE(left));
8871 #endif
8872
8873     /* I suppose that the left size >= result size */
8874     if(shCount == 0){
8875         while(size--){
8876             movLeft2Result(left, size, result, size);
8877         }
8878     }
8879
8880     else if(shCount >= (size * 8))
8881         while(size--)
8882             pic16_aopPut(AOP(result),zero,size);
8883     else{
8884         switch (size) {
8885             case 1:
8886                 genlshOne (result,left,shCount);
8887                 break;
8888
8889             case 2:
8890             case 3:
8891                 genlshTwo (result,left,shCount);
8892                 break;
8893
8894             case 4:
8895                 genlshFour (result,left,shCount);
8896                 break;
8897         }
8898     }
8899     pic16_freeAsmop(left,NULL,ic,TRUE);
8900     pic16_freeAsmop(result,NULL,ic,TRUE);
8901 }
8902
8903 /*-----------------------------------------------------------------*
8904  * genMultiAsm - repeat assembly instruction for size of register.
8905  * if endian == 1, then the high byte (i.e base address + size of 
8906  * register) is used first else the low byte is used first;
8907  *-----------------------------------------------------------------*/
8908 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8909 {
8910
8911   int offset = 0;
8912
8913   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8914
8915   if(!reg)
8916     return;
8917
8918   if(!endian) {
8919     endian = 1;
8920   } else {
8921     endian = -1;
8922     offset = size-1;
8923   }
8924
8925   while(size--) {
8926     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8927     offset += endian;
8928   }
8929
8930 }
8931 /*-----------------------------------------------------------------*/
8932 /* genLeftShift - generates code for left shifting                 */
8933 /*-----------------------------------------------------------------*/
8934 static void genLeftShift (iCode *ic)
8935 {
8936   operand *left,*right, *result;
8937   int size, offset;
8938 //  char *l;
8939   symbol *tlbl , *tlbl1;
8940   pCodeOp *pctemp;
8941
8942   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8943
8944   right = IC_RIGHT(ic);
8945   left  = IC_LEFT(ic);
8946   result = IC_RESULT(ic);
8947
8948   pic16_aopOp(right,ic,FALSE);
8949
8950   /* if the shift count is known then do it 
8951      as efficiently as possible */
8952   if (AOP_TYPE(right) == AOP_LIT) {
8953     genLeftShiftLiteral (left,right,result,ic);
8954     return ;
8955   }
8956
8957   /* shift count is unknown then we have to form
8958    * a loop. Get the loop count in WREG : Note: we take
8959    * only the lower order byte since shifting
8960    * more than 32 bits make no sense anyway, ( the
8961    * largest size of an object can be only 32 bits ) */
8962   
8963   pic16_aopOp(left,ic,FALSE);
8964   pic16_aopOp(result,ic,FALSE);
8965
8966   /* now move the left to the result if they are not the
8967    * same, and if size > 1,
8968    * and if right is not same to result (!!!) -- VR */
8969   if (!pic16_sameRegs(AOP(left),AOP(result))
8970       && (AOP_SIZE(result) > 1)) {
8971
8972     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8973
8974     size = AOP_SIZE(result);
8975     offset=0;
8976     while (size--) {
8977
8978 #if 0
8979       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8980       if (*l == '@' && (IS_AOP_PREG(result))) {
8981
8982           pic16_emitcode("mov","a,%s",l);
8983           pic16_aopPut(AOP(result),"a",offset);
8984       } else
8985 #endif
8986       {
8987         /* we don't know if left is a literal or a register, take care -- VR */
8988         mov2f(AOP(result), AOP(left), offset);
8989       }
8990       offset++;
8991     }
8992   }
8993
8994   size = AOP_SIZE(result);
8995
8996   /* if it is only one byte then */
8997   if (size == 1) {
8998     if(optimized_for_speed) {
8999       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9000       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9001       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9002       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9003       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9004       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9005       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9006       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9007       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9008       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9009       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9010       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9011     } else {
9012
9013       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9014
9015       tlbl = newiTempLabel(NULL);
9016
9017 #if 1
9018       /* this is already done, why change it? */
9019       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9020                 mov2f(AOP(result), AOP(left), 0);
9021       }
9022 #endif
9023
9024       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9025       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9026       pic16_emitpLabel(tlbl->key);
9027       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9028       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9029       emitSKPC;
9030       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9031     }
9032     goto release ;
9033   }
9034     
9035   if (pic16_sameRegs(AOP(left),AOP(result))) {
9036
9037     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9038     
9039     tlbl = newiTempLabel(NULL);
9040     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9041     genMultiAsm(POC_RRCF, result, size,1);
9042     pic16_emitpLabel(tlbl->key);
9043     genMultiAsm(POC_RLCF, result, size,0);
9044     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9045     emitSKPC;
9046     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9047     goto release;
9048   }
9049
9050   //tlbl = newiTempLabel(NULL);
9051   //offset = 0 ;   
9052   //tlbl1 = newiTempLabel(NULL);
9053
9054   //reAdjustPreg(AOP(result));    
9055     
9056   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9057   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9058   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9059   //MOVA(l);
9060   //pic16_emitcode("add","a,acc");         
9061   //pic16_aopPut(AOP(result),"a",offset++);
9062   //while (--size) {
9063   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9064   //  MOVA(l);
9065   //  pic16_emitcode("rlc","a");         
9066   //  pic16_aopPut(AOP(result),"a",offset++);
9067   //}
9068   //reAdjustPreg(AOP(result));
9069
9070   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9071   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9072
9073
9074   tlbl = newiTempLabel(NULL);
9075   tlbl1= newiTempLabel(NULL);
9076
9077   size = AOP_SIZE(result);
9078   offset = 1;
9079
9080   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9081
9082   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9083
9084   /* offset should be 0, 1 or 3 */
9085   
9086   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9087   emitSKPNZ;
9088   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9089
9090   pic16_emitpcode(POC_MOVWF, pctemp);
9091
9092
9093   pic16_emitpLabel(tlbl->key);
9094
9095   emitCLRC;
9096   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9097   while(--size)
9098     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9099
9100   pic16_emitpcode(POC_DECFSZ,  pctemp);
9101   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9102   pic16_emitpLabel(tlbl1->key);
9103
9104   pic16_popReleaseTempReg(pctemp,1);
9105
9106
9107  release:
9108   pic16_freeAsmop (right,NULL,ic,TRUE);
9109   pic16_freeAsmop(left,NULL,ic,TRUE);
9110   pic16_freeAsmop(result,NULL,ic,TRUE);
9111 }
9112
9113
9114
9115 #if 0
9116 #error old code (left here for reference)
9117 /*-----------------------------------------------------------------*/
9118 /* genLeftShift - generates code for left shifting                 */
9119 /*-----------------------------------------------------------------*/
9120 static void genLeftShift (iCode *ic)
9121 {
9122   operand *left,*right, *result;
9123   int size, offset;
9124   char *l;
9125   symbol *tlbl , *tlbl1;
9126   pCodeOp *pctemp;
9127
9128   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9129
9130   right = IC_RIGHT(ic);
9131   left  = IC_LEFT(ic);
9132   result = IC_RESULT(ic);
9133
9134   pic16_aopOp(right,ic,FALSE);
9135
9136   /* if the shift count is known then do it 
9137      as efficiently as possible */
9138   if (AOP_TYPE(right) == AOP_LIT) {
9139     genLeftShiftLiteral (left,right,result,ic);
9140     return ;
9141   }
9142
9143   /* shift count is unknown then we have to form 
9144      a loop get the loop count in B : Note: we take
9145      only the lower order byte since shifting
9146      more that 32 bits make no sense anyway, ( the
9147      largest size of an object can be only 32 bits ) */  
9148
9149     
9150   pic16_aopOp(left,ic,FALSE);
9151   pic16_aopOp(result,ic,FALSE);
9152
9153   /* now move the left to the result if they are not the
9154      same */
9155   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9156       AOP_SIZE(result) > 1) {
9157
9158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9159
9160     size = AOP_SIZE(result);
9161     offset=0;
9162     while (size--) {
9163       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9164       if (*l == '@' && (IS_AOP_PREG(result))) {
9165
9166         pic16_emitcode("mov","a,%s",l);
9167         pic16_aopPut(AOP(result),"a",offset);
9168       } else {
9169
9170         /* we don't know if left is a literal or a register, take care -- VR */
9171         mov2f(AOP(result), AOP(left), offset);
9172       }
9173       offset++;
9174     }
9175   }
9176
9177   size = AOP_SIZE(result);
9178
9179   /* if it is only one byte then */
9180   if (size == 1) {
9181     if(optimized_for_speed) {
9182       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9183       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9184       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9185       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9186       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9187       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9188       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9189       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9190       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9191       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9192       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9193       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9194     } else {
9195
9196       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9197
9198       tlbl = newiTempLabel(NULL);
9199       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9200                 mov2f(AOP(result), AOP(left), 0);
9201                 
9202 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9203 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9204       }
9205
9206       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9207       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9208       pic16_emitpLabel(tlbl->key);
9209       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9210       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9211       emitSKPC;
9212       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9213     }
9214     goto release ;
9215   }
9216     
9217   if (pic16_sameRegs(AOP(left),AOP(result))) {
9218
9219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9220     
9221     tlbl = newiTempLabel(NULL);
9222     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9223     genMultiAsm(POC_RRCF, result, size,1);
9224     pic16_emitpLabel(tlbl->key);
9225     genMultiAsm(POC_RLCF, result, size,0);
9226     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9227     emitSKPC;
9228     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9229     goto release;
9230   }
9231
9232   //tlbl = newiTempLabel(NULL);
9233   //offset = 0 ;   
9234   //tlbl1 = newiTempLabel(NULL);
9235
9236   //reAdjustPreg(AOP(result));    
9237     
9238   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9239   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9240   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9241   //MOVA(l);
9242   //pic16_emitcode("add","a,acc");         
9243   //pic16_aopPut(AOP(result),"a",offset++);
9244   //while (--size) {
9245   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9246   //  MOVA(l);
9247   //  pic16_emitcode("rlc","a");         
9248   //  pic16_aopPut(AOP(result),"a",offset++);
9249   //}
9250   //reAdjustPreg(AOP(result));
9251
9252   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9253   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9254
9255
9256   tlbl = newiTempLabel(NULL);
9257   tlbl1= newiTempLabel(NULL);
9258
9259   size = AOP_SIZE(result);
9260   offset = 1;
9261
9262   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9263
9264   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9265
9266   /* offset should be 0, 1 or 3 */
9267   
9268   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9269   emitSKPNZ;
9270   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9271
9272   pic16_emitpcode(POC_MOVWF, pctemp);
9273
9274
9275   pic16_emitpLabel(tlbl->key);
9276
9277   emitCLRC;
9278   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9279   while(--size)
9280     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9281
9282   pic16_emitpcode(POC_DECFSZ,  pctemp);
9283   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9284   pic16_emitpLabel(tlbl1->key);
9285
9286   pic16_popReleaseTempReg(pctemp,1);
9287
9288
9289  release:
9290   pic16_freeAsmop (right,NULL,ic,TRUE);
9291   pic16_freeAsmop(left,NULL,ic,TRUE);
9292   pic16_freeAsmop(result,NULL,ic,TRUE);
9293 }
9294 #endif
9295
9296 /*-----------------------------------------------------------------*/
9297 /* genrshOne - right shift a one byte quantity by known count      */
9298 /*-----------------------------------------------------------------*/
9299 static void genrshOne (operand *result, operand *left,
9300                        int shCount, int sign)
9301 {
9302     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9303     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9304 }
9305
9306 /*-----------------------------------------------------------------*/
9307 /* genrshTwo - right shift two bytes by known amount != 0          */
9308 /*-----------------------------------------------------------------*/
9309 static void genrshTwo (operand *result,operand *left,
9310                        int shCount, int sign)
9311 {
9312   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9313   /* if shCount >= 8 */
9314   if (shCount >= 8) {
9315     shCount -= 8 ;
9316     if (shCount)
9317       shiftR1Left2Result(left, MSB16, result, LSB,
9318                          shCount, sign);
9319     else
9320       movLeft2Result(left, MSB16, result, LSB);
9321
9322     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9323
9324     if(sign) {
9325       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9326       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9327     }
9328   }
9329
9330   /*  1 <= shCount <= 7 */
9331   else
9332     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9333 }
9334
9335 /*-----------------------------------------------------------------*/
9336 /* shiftRLong - shift right one long from left to result           */
9337 /* offl = LSB or MSB16                                             */
9338 /*-----------------------------------------------------------------*/
9339 static void shiftRLong (operand *left, int offl,
9340                         operand *result, int sign)
9341 {
9342     int size = AOP_SIZE(result);
9343     int same = pic16_sameRegs(AOP(left),AOP(result));
9344     int i;
9345     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9346
9347         if (same && (offl == MSB16)) { //shift one byte right
9348                 for(i=MSB16;i<size;i++) {
9349                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9350                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9351                 }
9352         }
9353
9354     if(sign)
9355                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9356         else
9357                 emitCLRC;
9358
9359         if (same) {
9360                 if (offl == LSB)
9361                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9362         } else {
9363         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9364         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9365         }
9366
9367     if(offl == MSB16) {
9368         /* add sign of "a" */
9369         pic16_addSign(result, MSB32, sign);
9370         }
9371
9372         if (same) {
9373         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9374         } else {
9375         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9376         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9377         }
9378         
9379         if (same) {
9380         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9381         } else {
9382         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9383         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9384         }
9385
9386         if (same) {
9387         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9388         } else {
9389         if(offl == LSB){
9390                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9391                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9392         }
9393         }
9394 }
9395
9396 /*-----------------------------------------------------------------*/
9397 /* genrshFour - shift four byte by a known amount != 0             */
9398 /*-----------------------------------------------------------------*/
9399 static void genrshFour (operand *result, operand *left,
9400                         int shCount, int sign)
9401 {
9402   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9403   /* if shifting more that 3 bytes */
9404   if(shCount >= 24 ) {
9405     shCount -= 24;
9406     if(shCount)
9407       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9408     else
9409       movLeft2Result(left, MSB32, result, LSB);
9410
9411     pic16_addSign(result, MSB16, sign);
9412   }
9413   else if(shCount >= 16){
9414     shCount -= 16;
9415     if(shCount)
9416       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9417     else{
9418       movLeft2Result(left, MSB24, result, LSB);
9419       movLeft2Result(left, MSB32, result, MSB16);
9420     }
9421     pic16_addSign(result, MSB24, sign);
9422   }
9423   else if(shCount >= 8){
9424     shCount -= 8;
9425     if(shCount == 1)
9426       shiftRLong(left, MSB16, result, sign);
9427     else if(shCount == 0){
9428       movLeft2Result(left, MSB16, result, LSB);
9429       movLeft2Result(left, MSB24, result, MSB16);
9430       movLeft2Result(left, MSB32, result, MSB24);
9431       pic16_addSign(result, MSB32, sign);
9432     }
9433     else{ //shcount >= 2
9434       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9435       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9436       /* the last shift is signed */
9437       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9438       pic16_addSign(result, MSB32, sign);
9439     }
9440   }
9441   else{   /* 1 <= shCount <= 7 */
9442     if(shCount <= 2){
9443       shiftRLong(left, LSB, result, sign);
9444       if(shCount == 2)
9445         shiftRLong(result, LSB, result, sign);
9446     }
9447     else{
9448       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9449       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9450       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9451     }
9452   }
9453 }
9454
9455 /*-----------------------------------------------------------------*/
9456 /* genRightShiftLiteral - right shifting by known count            */
9457 /*-----------------------------------------------------------------*/
9458 static void genRightShiftLiteral (operand *left,
9459                                   operand *right,
9460                                   operand *result,
9461                                   iCode *ic,
9462                                   int sign)
9463 {    
9464   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9465   int lsize,res_size;
9466
9467   pic16_freeAsmop(right,NULL,ic,TRUE);
9468
9469   pic16_aopOp(left,ic,FALSE);
9470   pic16_aopOp(result,ic,FALSE);
9471
9472   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9473
9474 #if VIEW_SIZE
9475   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9476                  AOP_SIZE(left));
9477 #endif
9478
9479   lsize = pic16_getDataSize(left);
9480   res_size = pic16_getDataSize(result);
9481   /* test the LEFT size !!! */
9482
9483   /* I suppose that the left size >= result size */
9484   if(shCount == 0){
9485     while(res_size--)
9486       movLeft2Result(left, lsize, result, res_size);
9487   }
9488
9489   else if(shCount >= (lsize * 8)){
9490
9491     if(res_size == 1) {
9492       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9493       if(sign) {
9494         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9495         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9496       }
9497     } else {
9498
9499       if(sign) {
9500         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9501         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9502         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9503         while(res_size--)
9504           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9505
9506       } else {
9507
9508         while(res_size--)
9509           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9510       }
9511     }
9512   } else {
9513
9514     switch (res_size) {
9515     case 1:
9516       genrshOne (result,left,shCount,sign);
9517       break;
9518
9519     case 2:
9520       genrshTwo (result,left,shCount,sign);
9521       break;
9522
9523     case 4:
9524       genrshFour (result,left,shCount,sign);
9525       break;
9526     default :
9527       break;
9528     }
9529
9530   }
9531
9532   pic16_freeAsmop(left,NULL,ic,TRUE);
9533   pic16_freeAsmop(result,NULL,ic,TRUE);
9534 }
9535
9536 /*-----------------------------------------------------------------*/
9537 /* genSignedRightShift - right shift of signed number              */
9538 /*-----------------------------------------------------------------*/
9539 static void genSignedRightShift (iCode *ic)
9540 {
9541   operand *right, *left, *result;
9542   int size, offset;
9543   //  char *l;
9544   symbol *tlbl, *tlbl1 ;
9545   pCodeOp *pctemp;
9546
9547   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9548
9549   /* we do it the hard way put the shift count in b
9550      and loop thru preserving the sign */
9551   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9552
9553   right = IC_RIGHT(ic);
9554   left  = IC_LEFT(ic);
9555   result = IC_RESULT(ic);
9556
9557   pic16_aopOp(right,ic,FALSE);  
9558   pic16_aopOp(left,ic,FALSE);
9559   pic16_aopOp(result,ic,FALSE);
9560
9561
9562   if ( AOP_TYPE(right) == AOP_LIT) {
9563     genRightShiftLiteral (left,right,result,ic,1);
9564     return ;
9565   }
9566   /* shift count is unknown then we have to form 
9567      a loop get the loop count in B : Note: we take
9568      only the lower order byte since shifting
9569      more that 32 bits make no sense anyway, ( the
9570      largest size of an object can be only 32 bits ) */  
9571
9572   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9573   //pic16_emitcode("inc","b");
9574   //pic16_freeAsmop (right,NULL,ic,TRUE);
9575   //pic16_aopOp(left,ic,FALSE);
9576   //pic16_aopOp(result,ic,FALSE);
9577
9578   /* now move the left to the result if they are not the
9579      same */
9580   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9581       AOP_SIZE(result) > 1) {
9582
9583     size = AOP_SIZE(result);
9584     offset=0;
9585     while (size--) { 
9586       /*
9587         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9588         if (*l == '@' && IS_AOP_PREG(result)) {
9589
9590         pic16_emitcode("mov","a,%s",l);
9591         pic16_aopPut(AOP(result),"a",offset);
9592         } else
9593         pic16_aopPut(AOP(result),l,offset);
9594       */
9595       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9596       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9597
9598       offset++;
9599     }
9600   }
9601
9602   /* mov the highest order bit to OVR */    
9603   tlbl = newiTempLabel(NULL);
9604   tlbl1= newiTempLabel(NULL);
9605
9606   size = AOP_SIZE(result);
9607   offset = size - 1;
9608
9609   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9610
9611   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9612
9613   /* offset should be 0, 1 or 3 */
9614   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9615   emitSKPNZ;
9616   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9617
9618   pic16_emitpcode(POC_MOVWF, pctemp);
9619
9620
9621   pic16_emitpLabel(tlbl->key);
9622
9623   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9624   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9625
9626   while(--size) {
9627     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9628   }
9629
9630   pic16_emitpcode(POC_DECFSZ,  pctemp);
9631   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9632   pic16_emitpLabel(tlbl1->key);
9633
9634   pic16_popReleaseTempReg(pctemp,1);
9635 #if 0
9636   size = AOP_SIZE(result);
9637   offset = size - 1;
9638   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9639   pic16_emitcode("rlc","a");
9640   pic16_emitcode("mov","ov,c");
9641   /* if it is only one byte then */
9642   if (size == 1) {
9643     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9644     MOVA(l);
9645     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9646     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9647     pic16_emitcode("mov","c,ov");
9648     pic16_emitcode("rrc","a");
9649     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9650     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9651     pic16_aopPut(AOP(result),"a",0);
9652     goto release ;
9653   }
9654
9655   reAdjustPreg(AOP(result));
9656   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9657   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9658   pic16_emitcode("mov","c,ov");
9659   while (size--) {
9660     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9661     MOVA(l);
9662     pic16_emitcode("rrc","a");         
9663     pic16_aopPut(AOP(result),"a",offset--);
9664   }
9665   reAdjustPreg(AOP(result));
9666   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9667   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9668
9669  release:
9670 #endif
9671
9672   pic16_freeAsmop(left,NULL,ic,TRUE);
9673   pic16_freeAsmop(result,NULL,ic,TRUE);
9674   pic16_freeAsmop(right,NULL,ic,TRUE);
9675 }
9676
9677 /*-----------------------------------------------------------------*/
9678 /* genRightShift - generate code for right shifting                */
9679 /*-----------------------------------------------------------------*/
9680 static void genRightShift (iCode *ic)
9681 {
9682     operand *right, *left, *result;
9683     sym_link *letype ;
9684     int size, offset;
9685     char *l;
9686     symbol *tlbl, *tlbl1 ;
9687
9688     /* if signed then we do it the hard way preserve the
9689     sign bit moving it inwards */
9690     letype = getSpec(operandType(IC_LEFT(ic)));
9691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9692
9693     if (!SPEC_USIGN(letype)) {
9694         genSignedRightShift (ic);
9695         return ;
9696     }
9697
9698     /* signed & unsigned types are treated the same : i.e. the
9699     signed is NOT propagated inwards : quoting from the
9700     ANSI - standard : "for E1 >> E2, is equivalent to division
9701     by 2**E2 if unsigned or if it has a non-negative value,
9702     otherwise the result is implementation defined ", MY definition
9703     is that the sign does not get propagated */
9704
9705     right = IC_RIGHT(ic);
9706     left  = IC_LEFT(ic);
9707     result = IC_RESULT(ic);
9708
9709     pic16_aopOp(right,ic,FALSE);
9710
9711     /* if the shift count is known then do it 
9712     as efficiently as possible */
9713     if (AOP_TYPE(right) == AOP_LIT) {
9714         genRightShiftLiteral (left,right,result,ic, 0);
9715         return ;
9716     }
9717
9718     /* shift count is unknown then we have to form 
9719     a loop get the loop count in B : Note: we take
9720     only the lower order byte since shifting
9721     more that 32 bits make no sense anyway, ( the
9722     largest size of an object can be only 32 bits ) */  
9723
9724     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9725     pic16_emitcode("inc","b");
9726     pic16_aopOp(left,ic,FALSE);
9727     pic16_aopOp(result,ic,FALSE);
9728
9729     /* now move the left to the result if they are not the
9730     same */
9731     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9732         AOP_SIZE(result) > 1) {
9733
9734         size = AOP_SIZE(result);
9735         offset=0;
9736         while (size--) {
9737             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9738             if (*l == '@' && IS_AOP_PREG(result)) {
9739
9740                 pic16_emitcode("mov","a,%s",l);
9741                 pic16_aopPut(AOP(result),"a",offset);
9742             } else
9743                 pic16_aopPut(AOP(result),l,offset);
9744             offset++;
9745         }
9746     }
9747
9748     tlbl = newiTempLabel(NULL);
9749     tlbl1= newiTempLabel(NULL);
9750     size = AOP_SIZE(result);
9751     offset = size - 1;
9752
9753     /* if it is only one byte then */
9754     if (size == 1) {
9755
9756       tlbl = newiTempLabel(NULL);
9757       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9758         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9759         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9760       }
9761
9762       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9763       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9764       pic16_emitpLabel(tlbl->key);
9765       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9766       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9767       emitSKPC;
9768       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9769
9770       goto release ;
9771     }
9772
9773     reAdjustPreg(AOP(result));
9774     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9775     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9776     CLRC;
9777     while (size--) {
9778         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9779         MOVA(l);
9780         pic16_emitcode("rrc","a");         
9781         pic16_aopPut(AOP(result),"a",offset--);
9782     }
9783     reAdjustPreg(AOP(result));
9784
9785     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9786     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9787
9788 release:
9789     pic16_freeAsmop(left,NULL,ic,TRUE);
9790     pic16_freeAsmop (right,NULL,ic,TRUE);
9791     pic16_freeAsmop(result,NULL,ic,TRUE);
9792 }
9793
9794
9795 void pic16_loadFSR0(operand *op)
9796 {
9797         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9798 }
9799
9800 /*-----------------------------------------------------------------*/
9801 /* genUnpackBits - generates code for unpacking bits               */
9802 /*-----------------------------------------------------------------*/
9803 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9804 {    
9805     int shCnt ;
9806     int rlen = 0 ;
9807     sym_link *etype;
9808     int offset = 0 ;
9809
9810         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9811         etype = getSpec(operandType(result));
9812
9813         /* the following call to pic16_loadFSR0 is temporary until
9814          * optimization to handle single bit assignments is added
9815          * to the function. Until then use the old safe way! -- VR */
9816         pic16_loadFSR0( left );
9817  
9818         /* read the first byte  */
9819         switch (ptype) {
9820                 case POINTER:
9821                 case IPOINTER:
9822                 case PPOINTER:
9823                 case FPOINTER:
9824                 case GPOINTER:
9825                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9826                         break;
9827                 case CPOINTER:
9828                         pic16_emitcode("clr","a");
9829                         pic16_emitcode("movc","a","@a+dptr");
9830                         break;
9831         }
9832         
9833
9834         /* if we have bitdisplacement then it fits   */
9835         /* into this byte completely or if length is */
9836         /* less than a byte                          */
9837         if ((shCnt = SPEC_BSTR(etype)) || 
9838                 (SPEC_BLEN(etype) <= 8))  {
9839
9840                 /* shift right acc */
9841                 AccRsh(shCnt, 0);
9842
9843                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9844                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9845
9846 /* VR -- normally I would use the following, but since we use the hack,
9847  * to avoid the masking from AccRsh, why not mask it right now? */
9848
9849 /*
9850                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9851 */
9852
9853                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9854           return ;
9855         }
9856
9857
9858
9859         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9860         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9861         exit(-1);
9862
9863     /* bit field did not fit in a byte  */
9864     rlen = SPEC_BLEN(etype) - 8;
9865     pic16_aopPut(AOP(result),"a",offset++);
9866
9867     while (1)  {
9868
9869         switch (ptype) {
9870         case POINTER:
9871         case IPOINTER:
9872             pic16_emitcode("inc","%s",rname);
9873             pic16_emitcode("mov","a,@%s",rname);
9874             break;
9875             
9876         case PPOINTER:
9877             pic16_emitcode("inc","%s",rname);
9878             pic16_emitcode("movx","a,@%s",rname);
9879             break;
9880
9881         case FPOINTER:
9882             pic16_emitcode("inc","dptr");
9883             pic16_emitcode("movx","a,@dptr");
9884             break;
9885             
9886         case CPOINTER:
9887             pic16_emitcode("clr","a");
9888             pic16_emitcode("inc","dptr");
9889             pic16_emitcode("movc","a","@a+dptr");
9890             break;
9891             
9892         case GPOINTER:
9893             pic16_emitcode("inc","dptr");
9894             pic16_emitcode("lcall","__gptrget");
9895             break;
9896         }
9897
9898         rlen -= 8;            
9899         /* if we are done */
9900         if ( rlen <= 0 )
9901             break ;
9902         
9903         pic16_aopPut(AOP(result),"a",offset++);
9904                               
9905     }
9906     
9907     if (rlen) {
9908         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9909         pic16_aopPut(AOP(result),"a",offset);          
9910     }
9911     
9912     return ;
9913 }
9914
9915
9916 static void genDataPointerGet(operand *left,
9917                               operand *result,
9918                               iCode *ic)
9919 {
9920   int size, offset = 0, leoffset=0 ;
9921
9922         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9923         pic16_aopOp(result, ic, FALSE);
9924
9925         size = AOP_SIZE(result);
9926 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9927
9928
9929 #if 0
9930         /* The following tests may save a redudant movff instruction when
9931          * accessing unions */
9932          
9933         /* if they are the same */
9934         if (operandsEqu (left, result)) {
9935                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9936                 goto release;
9937         }
9938 #endif
9939
9940 #if 0
9941         /* if they are the same registers */
9942         if (pic16_sameRegs(AOP(left),AOP(result))) {
9943                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9944                 goto release;
9945         }
9946 #endif
9947
9948 #if 1
9949         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9950                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9951                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9952                 goto release;
9953         }
9954 #endif
9955
9956
9957 #if 0
9958         if ( AOP_TYPE(left) == AOP_PCODE) {
9959                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9960                                 AOP(left)->aopu.pcop->name,
9961                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9962                                 PCOR(AOP(left)->aopu.pcop)->instance:
9963                                 PCOI(AOP(left)->aopu.pcop)->offset);
9964         }
9965 #endif
9966
9967         if(AOP(left)->aopu.pcop->type == PO_DIR)
9968                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9969
9970         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9971
9972         while (size--) {
9973                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9974                 
9975                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9976                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9977                         mov2w(AOP(left), offset); // patch 8
9978                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9979                 } else {
9980                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9981                                 pic16_popGet(AOP(left), offset), //patch 8
9982                                 pic16_popGet(AOP(result), offset)));
9983                 }
9984
9985                 offset++;
9986                 leoffset++;
9987         }
9988
9989 release:
9990     pic16_freeAsmop(result,NULL,ic,TRUE);
9991 }
9992
9993
9994
9995 /*-----------------------------------------------------------------*/
9996 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9997 /*-----------------------------------------------------------------*/
9998 static void genNearPointerGet (operand *left, 
9999                                operand *result, 
10000                                iCode *ic)
10001 {
10002     asmop *aop = NULL;
10003     //regs *preg = NULL ;
10004     sym_link *rtype, *retype;
10005     sym_link *ltype = operandType(left);    
10006
10007         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10008         rtype = operandType(result);
10009         retype= getSpec(rtype);
10010     
10011         pic16_aopOp(left,ic,FALSE);
10012
10013 //      pic16_DumpOp("(left)",left);
10014 //      pic16_DumpOp("(result)",result);
10015
10016         /* if left is rematerialisable and
10017          * result is not bit variable type and
10018          * the left is pointer to data space i.e
10019          * lower 128 bytes of space */
10020         if (AOP_TYPE(left) == AOP_PCODE
10021                 && !IS_BITFIELD(retype)
10022                 && DCL_TYPE(ltype) == POINTER) {
10023
10024                 genDataPointerGet (left,result,ic);
10025                 pic16_freeAsmop(left, NULL, ic, TRUE);
10026           return ;
10027         }
10028     
10029         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10030
10031         /* if the value is already in a pointer register
10032          * then don't need anything more */
10033         if (!AOP_INPREG(AOP(left))) {
10034                 /* otherwise get a free pointer register */
10035                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10036                 
10037                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10038                 if( (AOP_TYPE(left) == AOP_PCODE) 
10039                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10040                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
10041                 {
10042                         if(!IS_BITFIELD(retype))
10043                                 pic16_loadFSR0( left );  // patch 10
10044                 } else {
10045                         // set up FSR0 with address from left
10046                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10047                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10048                 }
10049         }
10050 //       else
10051 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10052     
10053         pic16_aopOp (result,ic,FALSE);
10054     
10055       /* if bitfield then unpack the bits */
10056     if (IS_BITFIELD(retype)) 
10057         genUnpackBits (result, left, NULL, POINTER);
10058     else {
10059         /* we have can just get the values */
10060       int size = AOP_SIZE(result);
10061       int offset = 0;   
10062         
10063       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10064
10065
10066         /* fsr0 is loaded already -- VR */
10067 //      pic16_loadFSR0( left );
10068
10069 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10070 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10071       while(size--) {
10072
10073         if(size) {
10074                 pic16_emitpcode(POC_MOVFF,
10075                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10076                                 pic16_popGet(AOP(result), offset++)));
10077         } else {
10078                 pic16_emitpcode(POC_MOVFF,
10079                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10080                                 pic16_popGet(AOP(result), offset++)));
10081         }
10082       }
10083 #if 0
10084 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10085 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10086         if(size)
10087           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10088 #endif
10089 /*
10090         while (size--) {
10091             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10092
10093                 pic16_emitcode("mov","a,@%s",rname);
10094                 pic16_aopPut(AOP(result),"a",offset);
10095             } else {
10096                 sprintf(buffer,"@%s",rname);
10097                 pic16_aopPut(AOP(result),buffer,offset);
10098             }
10099             offset++ ;
10100             if (size)
10101                 pic16_emitcode("inc","%s",rname);
10102         }
10103 */
10104     }
10105
10106     /* now some housekeeping stuff */
10107     if (aop) {
10108         /* we had to allocate for this iCode */
10109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10110         pic16_freeAsmop(NULL,aop,ic,TRUE);
10111     } else { 
10112         /* we did not allocate which means left
10113            already in a pointer register, then
10114            if size > 0 && this could be used again
10115            we have to point it back to where it 
10116            belongs */
10117     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10118         if (AOP_SIZE(result) > 1 &&
10119             !OP_SYMBOL(left)->remat &&
10120             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10121               ic->depth )) {
10122 //          int size = AOP_SIZE(result) - 1;
10123 //          while (size--)
10124 //              pic16_emitcode("dec","%s",rname);
10125         }
10126     }
10127
10128     /* done */
10129     pic16_freeAsmop(left,NULL,ic,TRUE);
10130     pic16_freeAsmop(result,NULL,ic,TRUE);
10131      
10132 }
10133
10134 /*-----------------------------------------------------------------*/
10135 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10136 /*-----------------------------------------------------------------*/
10137 static void genPagedPointerGet (operand *left, 
10138                                operand *result, 
10139                                iCode *ic)
10140 {
10141     asmop *aop = NULL;
10142     regs *preg = NULL ;
10143     char *rname ;
10144     sym_link *rtype, *retype;    
10145
10146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10147
10148     rtype = operandType(result);
10149     retype= getSpec(rtype);
10150     
10151     pic16_aopOp(left,ic,FALSE);
10152
10153   /* if the value is already in a pointer register
10154        then don't need anything more */
10155     if (!AOP_INPREG(AOP(left))) {
10156         /* otherwise get a free pointer register */
10157         aop = newAsmop(0);
10158         preg = getFreePtr(ic,&aop,FALSE);
10159         pic16_emitcode("mov","%s,%s",
10160                 preg->name,
10161                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10162         rname = preg->name ;
10163     } else
10164         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10165     
10166     pic16_freeAsmop(left,NULL,ic,TRUE);
10167     pic16_aopOp (result,ic,FALSE);
10168
10169     /* if bitfield then unpack the bits */
10170     if (IS_BITFIELD(retype)) 
10171         genUnpackBits (result,left,rname,PPOINTER);
10172     else {
10173         /* we have can just get the values */
10174         int size = AOP_SIZE(result);
10175         int offset = 0 ;        
10176         
10177         while (size--) {
10178             
10179             pic16_emitcode("movx","a,@%s",rname);
10180             pic16_aopPut(AOP(result),"a",offset);
10181             
10182             offset++ ;
10183             
10184             if (size)
10185                 pic16_emitcode("inc","%s",rname);
10186         }
10187     }
10188
10189     /* now some housekeeping stuff */
10190     if (aop) {
10191         /* we had to allocate for this iCode */
10192         pic16_freeAsmop(NULL,aop,ic,TRUE);
10193     } else { 
10194         /* we did not allocate which means left
10195            already in a pointer register, then
10196            if size > 0 && this could be used again
10197            we have to point it back to where it 
10198            belongs */
10199         if (AOP_SIZE(result) > 1 &&
10200             !OP_SYMBOL(left)->remat &&
10201             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10202               ic->depth )) {
10203             int size = AOP_SIZE(result) - 1;
10204             while (size--)
10205                 pic16_emitcode("dec","%s",rname);
10206         }
10207     }
10208
10209     /* done */
10210     pic16_freeAsmop(result,NULL,ic,TRUE);
10211     
10212         
10213 }
10214
10215 /*-----------------------------------------------------------------*/
10216 /* genFarPointerGet - gget value from far space                    */
10217 /*-----------------------------------------------------------------*/
10218 static void genFarPointerGet (operand *left,
10219                               operand *result, iCode *ic)
10220 {
10221     int size, offset ;
10222     sym_link *retype = getSpec(operandType(result));
10223
10224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10225
10226     pic16_aopOp(left,ic,FALSE);
10227
10228     /* if the operand is already in dptr 
10229     then we do nothing else we move the value to dptr */
10230     if (AOP_TYPE(left) != AOP_STR) {
10231         /* if this is remateriazable */
10232         if (AOP_TYPE(left) == AOP_IMMD)
10233             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10234         else { /* we need to get it byte by byte */
10235             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10236             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10237             if (options.model == MODEL_FLAT24)
10238             {
10239                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10240             }
10241         }
10242     }
10243     /* so dptr know contains the address */
10244     pic16_freeAsmop(left,NULL,ic,TRUE);
10245     pic16_aopOp(result,ic,FALSE);
10246
10247     /* if bit then unpack */
10248     if (IS_BITFIELD(retype)) 
10249         genUnpackBits(result,left,"dptr",FPOINTER);
10250     else {
10251         size = AOP_SIZE(result);
10252         offset = 0 ;
10253
10254         while (size--) {
10255             pic16_emitcode("movx","a,@dptr");
10256             pic16_aopPut(AOP(result),"a",offset++);
10257             if (size)
10258                 pic16_emitcode("inc","dptr");
10259         }
10260     }
10261
10262     pic16_freeAsmop(result,NULL,ic,TRUE);
10263 }
10264 #if 0
10265 /*-----------------------------------------------------------------*/
10266 /* genCodePointerGet - get value from code space                  */
10267 /*-----------------------------------------------------------------*/
10268 static void genCodePointerGet (operand *left,
10269                                 operand *result, iCode *ic)
10270 {
10271     int size, offset ;
10272     sym_link *retype = getSpec(operandType(result));
10273
10274     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10275
10276     pic16_aopOp(left,ic,FALSE);
10277
10278     /* if the operand is already in dptr 
10279     then we do nothing else we move the value to dptr */
10280     if (AOP_TYPE(left) != AOP_STR) {
10281         /* if this is remateriazable */
10282         if (AOP_TYPE(left) == AOP_IMMD)
10283             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10284         else { /* we need to get it byte by byte */
10285             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10286             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10287             if (options.model == MODEL_FLAT24)
10288             {
10289                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10290             }
10291         }
10292     }
10293     /* so dptr know contains the address */
10294     pic16_freeAsmop(left,NULL,ic,TRUE);
10295     pic16_aopOp(result,ic,FALSE);
10296
10297     /* if bit then unpack */
10298     if (IS_BITFIELD(retype)) 
10299         genUnpackBits(result,left,"dptr",CPOINTER);
10300     else {
10301         size = AOP_SIZE(result);
10302         offset = 0 ;
10303
10304         while (size--) {
10305             pic16_emitcode("clr","a");
10306             pic16_emitcode("movc","a,@a+dptr");
10307             pic16_aopPut(AOP(result),"a",offset++);
10308             if (size)
10309                 pic16_emitcode("inc","dptr");
10310         }
10311     }
10312
10313     pic16_freeAsmop(result,NULL,ic,TRUE);
10314 }
10315 #endif
10316 #if 0
10317 /*-----------------------------------------------------------------*/
10318 /* genGenPointerGet - gget value from generic pointer space        */
10319 /*-----------------------------------------------------------------*/
10320 static void genGenPointerGet (operand *left,
10321                               operand *result, iCode *ic)
10322 {
10323   int size, offset, lit;
10324   sym_link *retype = getSpec(operandType(result));
10325
10326         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10327         pic16_aopOp(left,ic,FALSE);
10328         pic16_aopOp(result,ic,FALSE);
10329         size = AOP_SIZE(result);
10330
10331         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10332
10333         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10334
10335                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10336                 // load FSR0 from immediate
10337                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10338
10339 //              pic16_loadFSR0( left );
10340
10341                 offset = 0;
10342                 while(size--) {
10343                         if(size) {
10344                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10345                         } else {
10346                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10347                         }
10348                         offset++;
10349                 }
10350                 goto release;
10351
10352         }
10353         else { /* we need to get it byte by byte */
10354                 // set up FSR0 with address from left
10355                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10356                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10357
10358                 offset = 0 ;
10359
10360                 while(size--) {
10361                         if(size) {
10362                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10363                         } else {
10364                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10365                         }
10366                         offset++;
10367                 }
10368                 goto release;
10369         }
10370
10371   /* if bit then unpack */
10372         if (IS_BITFIELD(retype)) 
10373                 genUnpackBits(result,left,"BAD",GPOINTER);
10374
10375         release:
10376         pic16_freeAsmop(left,NULL,ic,TRUE);
10377         pic16_freeAsmop(result,NULL,ic,TRUE);
10378
10379 }
10380 #endif
10381
10382 extern set *externs;
10383
10384 /*-----------------------------------------------------------------*/
10385 /* genGenPointerGet - gget value from generic pointer space        */
10386 /*-----------------------------------------------------------------*/
10387 static void genGenPointerGet (operand *left,
10388                               operand *result, iCode *ic)
10389 {
10390   int size, offset, lit;
10391   sym_link *retype = getSpec(operandType(result));
10392   char fgptrget[32];
10393
10394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10395     pic16_aopOp(left,ic,FALSE);
10396     pic16_aopOp(result,ic,FALSE);
10397     size = AOP_SIZE(result);
10398
10399     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10400
10401     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10402
10403       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10404       // load FSR0 from immediate
10405       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10406
10407       werror(W_POSSBUG2, __FILE__, __LINE__);
10408
10409       offset = 0;
10410       while(size--) {
10411         if(size) {
10412           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10413         } else {
10414           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10415         }
10416         offset++;
10417       }
10418
10419       goto release;
10420
10421     } else { /* we need to get it byte by byte */
10422
10423       /* set up WREG:PRODL:FSR0L with address from left */
10424       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10425       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10426       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10427       
10428       switch( size ) {
10429         case 1: strcpy(fgptrget, "__gptrget1"); break;
10430         case 2: strcpy(fgptrget, "__gptrget2"); break;
10431         case 3: strcpy(fgptrget, "__gptrget3"); break;
10432         case 4: strcpy(fgptrget, "__gptrget4"); break;
10433         default:
10434           werror(W_POSSBUG2, __FILE__, __LINE__);
10435           abort();
10436       }
10437       
10438       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10439       
10440       assignResultValue(result, 1);
10441       
10442       {
10443         symbol *sym;
10444
10445           sym = newSymbol( fgptrget, 0 );
10446           strcpy(sym->rname, fgptrget);
10447           checkAddSym(&externs, sym);
10448
10449 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10450       }
10451               
10452       goto release;
10453     }
10454
10455   /* if bit then unpack */
10456     if (IS_BITFIELD(retype)) 
10457       genUnpackBits(result,left,"BAD",GPOINTER);
10458
10459 release:
10460   pic16_freeAsmop(left,NULL,ic,TRUE);
10461   pic16_freeAsmop(result,NULL,ic,TRUE);
10462 }
10463
10464 /*-----------------------------------------------------------------*/
10465 /* genConstPointerGet - get value from const generic pointer space */
10466 /*-----------------------------------------------------------------*/
10467 static void genConstPointerGet (operand *left,
10468                                 operand *result, iCode *ic)
10469 {
10470   //sym_link *retype = getSpec(operandType(result));
10471   // symbol *albl = newiTempLabel(NULL);        // patch 15
10472   // symbol *blbl = newiTempLabel(NULL);        //
10473   // PIC_OPCODE poc;                            // patch 15
10474   int size;
10475   int offset = 0;
10476
10477   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10478   pic16_aopOp(left,ic,FALSE);
10479   pic16_aopOp(result,ic,TRUE);
10480   size = AOP_SIZE(result);
10481
10482   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10483
10484   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10485 #if 0                                                                   // patch 15
10486   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10487   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10488   pic16_emitpLabel(albl->key);
10489
10490   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10491   
10492   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10493   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10494   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10495   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10496   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10497
10498   pic16_emitpLabel(blbl->key);
10499
10500   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10501 #endif                                                                  // patch 15
10502
10503
10504   // set up table pointer
10505   if( (AOP_TYPE(left) == AOP_PCODE) 
10506       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10507           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
10508     {
10509       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
10510       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10511       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
10512       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10513       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
10514       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10515     }
10516   else
10517     {
10518       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
10519       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
10520       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
10521     }
10522
10523
10524   while(size--)
10525     {
10526       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10527       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
10528       offset++;
10529     }
10530     
10531   pic16_freeAsmop(left,NULL,ic,TRUE);
10532   pic16_freeAsmop(result,NULL,ic,TRUE);
10533
10534 }
10535
10536
10537 /*-----------------------------------------------------------------*/
10538 /* genPointerGet - generate code for pointer get                   */
10539 /*-----------------------------------------------------------------*/
10540 static void genPointerGet (iCode *ic)
10541 {
10542     operand *left, *result ;
10543     sym_link *type, *etype;
10544     int p_type;
10545
10546     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10547
10548     left = IC_LEFT(ic);
10549     result = IC_RESULT(ic) ;
10550
10551     /* depending on the type of pointer we need to
10552     move it to the correct pointer register */
10553     type = operandType(left);
10554     etype = getSpec(type);
10555
10556 #if 0
10557     if (IS_PTR_CONST(type))
10558 #else
10559     if (IS_CODEPTR(type))
10560 #endif
10561       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
10562
10563     /* if left is of type of pointer then it is simple */
10564     if (IS_PTR(type) && !IS_FUNC(type->next)) 
10565         p_type = DCL_TYPE(type);
10566     else {
10567         /* we have to go by the storage class */
10568         p_type = PTR_TYPE(SPEC_OCLS(etype));
10569
10570         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
10571
10572         if (SPEC_OCLS(etype)->codesp ) {
10573           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
10574           //p_type = CPOINTER ; 
10575         }
10576         else
10577             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
10578               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
10579                /*p_type = FPOINTER ;*/ 
10580             else
10581                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
10582                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
10583 /*                  p_type = PPOINTER; */
10584                 else
10585                     if (SPEC_OCLS(etype) == idata )
10586                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
10587 /*                      p_type = IPOINTER; */
10588                     else
10589                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
10590 /*                      p_type = POINTER ; */
10591     }
10592
10593     /* now that we have the pointer type we assign
10594     the pointer values */
10595     switch (p_type) {
10596
10597     case POINTER:       
10598     case IPOINTER:
10599         genNearPointerGet (left,result,ic);
10600         break;
10601
10602     case PPOINTER:
10603         genPagedPointerGet(left,result,ic);
10604         break;
10605
10606     case FPOINTER:
10607         genFarPointerGet (left,result,ic);
10608         break;
10609
10610     case CPOINTER:
10611         genConstPointerGet (left,result,ic);
10612         //pic16_emitcodePointerGet (left,result,ic);
10613         break;
10614
10615     case GPOINTER:
10616 #if 0
10617       if (IS_PTR_CONST(type))
10618         genConstPointerGet (left,result,ic);
10619       else
10620 #endif
10621         genGenPointerGet (left,result,ic);
10622       break;
10623
10624     default:
10625       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10626               "genPointerGet: illegal pointer type");
10627     
10628     }
10629
10630 }
10631
10632 /*-----------------------------------------------------------------*/
10633 /* genPackBits - generates code for packed bit storage             */
10634 /*-----------------------------------------------------------------*/
10635 static void genPackBits (sym_link    *etype , operand *result,
10636                          operand *right ,
10637                          char *rname, int p_type)
10638 {
10639   int shCnt = 0 ;
10640   int offset = 0  ;
10641   int rLen = 0 ;
10642   int blen, bstr ;   
10643   char *l ;
10644
10645         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10646         blen = SPEC_BLEN(etype);
10647         bstr = SPEC_BSTR(etype);
10648
10649         if(AOP_TYPE(right) == AOP_LIT) {
10650                 if((blen == 1) && (bstr < 8)) {
10651                   unsigned long lit;
10652                         /* it is a single bit, so use the appropriate bit instructions */
10653
10654                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
10655
10656                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10657 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10658                         if((p_type == POINTER) && (result)) {
10659                                 /* workaround to reduce the extra lfsr instruction */
10660                                 if(lit) {
10661                                         pic16_emitpcode(POC_BSF,
10662                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10663                                 } else {
10664                                         pic16_emitpcode(POC_BCF,
10665                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10666                                 }
10667                         } else {
10668
10669                                 if(lit) {
10670                                         pic16_emitpcode(POC_BSF,
10671                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10672                                 } else {
10673                                         pic16_emitpcode(POC_BCF,
10674                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10675                                 }
10676                         }
10677         
10678                   return;
10679                 }
10680
10681                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10682                 offset++;
10683         } else
10684                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10685
10686         /* if the bit lenth is less than or    */
10687         /* it exactly fits a byte then         */
10688         if((shCnt=SPEC_BSTR(etype))
10689                 || SPEC_BLEN(etype) <= 8 )  {
10690
10691                 /* shift left acc */
10692                 AccLsh(shCnt);
10693
10694                 /* using PRODL as a temporary register here */
10695                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10696
10697                 switch (p_type) {
10698                         case FPOINTER:
10699                         case POINTER:
10700                         case GPOINTER:
10701                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10702 //                              pic16_emitcode ("mov","b,a");
10703 //                              pic16_emitcode("mov","a,@%s",rname);
10704                                 break;
10705                 }
10706 #if 1
10707                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10708                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10709                                         (unsigned char)(0xff >> (8-bstr))) ));
10710                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10711                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10712 #endif
10713
10714           return;
10715         }
10716
10717
10718         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10719         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10720         exit(-1);
10721
10722
10723     /* if we r done */
10724     if ( SPEC_BLEN(etype) <= 8 )
10725         return ;
10726
10727     pic16_emitcode("inc","%s",rname);
10728     rLen = SPEC_BLEN(etype) ;     
10729
10730
10731
10732     /* now generate for lengths greater than one byte */
10733     while (1) {
10734
10735         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10736
10737         rLen -= 8 ;
10738         if (rLen <= 0 )
10739             break ;
10740
10741         switch (p_type) {
10742             case POINTER:
10743                 if (*l == '@') {
10744                     MOVA(l);
10745                     pic16_emitcode("mov","@%s,a",rname);
10746                 } else
10747                     pic16_emitcode("mov","@%s,%s",rname,l);
10748                 break;
10749
10750             case FPOINTER:
10751                 MOVA(l);
10752                 pic16_emitcode("movx","@dptr,a");
10753                 break;
10754
10755             case GPOINTER:
10756                 MOVA(l);
10757                 DEBUGpic16_emitcode(";lcall","__gptrput");
10758                 break;  
10759         }   
10760         pic16_emitcode ("inc","%s",rname);
10761     }
10762
10763     MOVA(l);
10764
10765     /* last last was not complete */
10766     if (rLen)   {
10767         /* save the byte & read byte */
10768         switch (p_type) {
10769             case POINTER:
10770                 pic16_emitcode ("mov","b,a");
10771                 pic16_emitcode("mov","a,@%s",rname);
10772                 break;
10773
10774             case FPOINTER:
10775                 pic16_emitcode ("mov","b,a");
10776                 pic16_emitcode("movx","a,@dptr");
10777                 break;
10778
10779             case GPOINTER:
10780                 pic16_emitcode ("push","b");
10781                 pic16_emitcode ("push","acc");
10782                 pic16_emitcode ("lcall","__gptrget");
10783                 pic16_emitcode ("pop","b");
10784                 break;
10785         }
10786
10787         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10788         pic16_emitcode ("orl","a,b");
10789     }
10790
10791     if (p_type == GPOINTER)
10792         pic16_emitcode("pop","b");
10793
10794     switch (p_type) {
10795
10796     case POINTER:
10797         pic16_emitcode("mov","@%s,a",rname);
10798         break;
10799         
10800     case FPOINTER:
10801         pic16_emitcode("movx","@dptr,a");
10802         break;
10803         
10804     case GPOINTER:
10805         DEBUGpic16_emitcode(";lcall","__gptrput");
10806         break;                  
10807     }
10808 }
10809 /*-----------------------------------------------------------------*/
10810 /* genDataPointerSet - remat pointer to data space                 */
10811 /*-----------------------------------------------------------------*/
10812 static void genDataPointerSet(operand *right,
10813                               operand *result,
10814                               iCode *ic)
10815 {
10816     int size, offset = 0, resoffset=0 ;
10817
10818     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10819     pic16_aopOp(right,ic,FALSE);
10820
10821     size = AOP_SIZE(right);
10822
10823 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10824
10825 #if 0
10826     if ( AOP_TYPE(result) == AOP_PCODE) {
10827       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10828               AOP(result)->aopu.pcop->name,
10829                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10830               PCOR(AOP(result)->aopu.pcop)->instance:
10831               PCOI(AOP(result)->aopu.pcop)->offset);
10832     }
10833 #endif
10834
10835         if(AOP(result)->aopu.pcop->type == PO_DIR)
10836                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10837
10838         while (size--) {
10839                 if (AOP_TYPE(right) == AOP_LIT) {
10840                   unsigned int lit;
10841
10842                     if(!IS_FLOAT(operandType( right )))
10843                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
10844                     else {
10845                       union {
10846                         unsigned long lit_int;
10847                         float lit_float;
10848                       } info;
10849         
10850                         /* take care if literal is a float */
10851                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
10852                         lit = info.lit_int;
10853                     }
10854
10855                     lit = lit >> (8*offset);
10856                     if(lit&0xff) {
10857                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10858                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10859                     } else {
10860                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10861                     }
10862                 } else {
10863                   mov2w(AOP(right), offset);
10864                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10865                 }
10866                 offset++;
10867                 resoffset++;
10868         }
10869
10870     pic16_freeAsmop(right,NULL,ic,TRUE);
10871 }
10872
10873
10874
10875 /*-----------------------------------------------------------------*/
10876 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10877 /*-----------------------------------------------------------------*/
10878 static void genNearPointerSet (operand *right,
10879                                operand *result, 
10880                                iCode *ic)
10881 {
10882   asmop *aop = NULL;
10883   char *l;
10884   sym_link *retype;
10885   sym_link *ptype = operandType(result);
10886   sym_link *resetype;
10887     
10888         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10889         retype= getSpec(operandType(right));
10890         resetype = getSpec(operandType(result));
10891   
10892         pic16_aopOp(result,ic,FALSE);
10893     
10894         /* if the result is rematerializable &
10895          * in data space & not a bit variable */
10896         
10897         /* and result is not a bit variable */
10898         if (AOP_TYPE(result) == AOP_PCODE
10899 //              && AOP_TYPE(result) == AOP_IMMD
10900                 && DCL_TYPE(ptype) == POINTER
10901                 && !IS_BITFIELD(retype)
10902                 && !IS_BITFIELD(resetype)) {
10903
10904                 genDataPointerSet (right,result,ic);
10905                 pic16_freeAsmop(result,NULL,ic,TRUE);
10906           return;
10907         }
10908
10909         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10910         pic16_aopOp(right,ic,FALSE);
10911         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10912
10913         /* if the value is already in a pointer register
10914          * then don't need anything more */
10915         if (!AOP_INPREG(AOP(result))) {
10916                 /* otherwise get a free pointer register */
10917                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10918
10919                 if( (AOP_TYPE(result) == AOP_PCODE) 
10920                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10921                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10922                 {
10923                   if(!IS_BITFIELD(resetype))
10924                         pic16_loadFSR0( result );  // patch 10
10925                 } else {
10926                         // set up FSR0 with address of result
10927                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10928                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10929                 }
10930
10931         }
10932 //      else
10933 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10934
10935         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10936
10937         /* if bitfield then unpack the bits */
10938         if (IS_BITFIELD(resetype)) {
10939                 genPackBits (resetype, result, right, NULL, POINTER);
10940         } else {
10941                 /* we have can just get the values */
10942           int size = AOP_SIZE(right);
10943           int offset = 0 ;    
10944
10945                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10946                 while (size--) {
10947                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10948                         if (*l == '@' ) {
10949                                 //MOVA(l);
10950                                 //pic16_emitcode("mov","@%s,a",rname);
10951                                 pic16_emitcode("movf","indf0,w ;1");
10952                         } else {
10953
10954                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10955                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10956                                         if (size) {                                                                     // 
10957                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10958                                         } else {                                                                        // 
10959                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10960                                         }                                                                               // 
10961                                 } else { // no literal                                                                  // 
10962                                         if(size) {                                                                      // 
10963                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10964                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10965                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10966                                         } else {                                                                        // 
10967                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10968                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10969                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10970                                         }                                                                               //
10971                                 }                                                                                       // patch 10
10972                         }
10973                         offset++;
10974                 }
10975         }
10976
10977         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10978         /* now some housekeeping stuff */
10979         if (aop) {
10980                 /* we had to allocate for this iCode */
10981                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10982         } else { 
10983                 /* we did not allocate which means left
10984                  * already in a pointer register, then
10985                  * if size > 0 && this could be used again
10986                  * we have to point it back to where it 
10987                  * belongs */
10988                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10989                 if (AOP_SIZE(right) > 1
10990                         && !OP_SYMBOL(result)->remat
10991                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10992                                 || ic->depth )) {
10993
10994                   int size = AOP_SIZE(right) - 1;
10995
10996                         while (size--)
10997                                 pic16_emitcode("decf","fsr0,f");
10998                         //pic16_emitcode("dec","%s",rname);
10999                 }
11000         }
11001
11002         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11003         /* done */
11004 //release:
11005         pic16_freeAsmop(right,NULL,ic,TRUE);
11006         pic16_freeAsmop(result,NULL,ic,TRUE);
11007 }
11008
11009 /*-----------------------------------------------------------------*/
11010 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11011 /*-----------------------------------------------------------------*/
11012 static void genPagedPointerSet (operand *right,
11013                                operand *result, 
11014                                iCode *ic)
11015 {
11016     asmop *aop = NULL;
11017     regs *preg = NULL ;
11018     char *rname , *l;
11019     sym_link *retype;
11020        
11021     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11022
11023     retype= getSpec(operandType(right));
11024     
11025     pic16_aopOp(result,ic,FALSE);
11026     
11027     /* if the value is already in a pointer register
11028        then don't need anything more */
11029     if (!AOP_INPREG(AOP(result))) {
11030         /* otherwise get a free pointer register */
11031         aop = newAsmop(0);
11032         preg = getFreePtr(ic,&aop,FALSE);
11033         pic16_emitcode("mov","%s,%s",
11034                 preg->name,
11035                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11036         rname = preg->name ;
11037     } else
11038         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11039     
11040     pic16_freeAsmop(result,NULL,ic,TRUE);
11041     pic16_aopOp (right,ic,FALSE);
11042
11043     /* if bitfield then unpack the bits */
11044     if (IS_BITFIELD(retype)) 
11045         genPackBits (retype,result,right,rname,PPOINTER);
11046     else {
11047         /* we have can just get the values */
11048         int size = AOP_SIZE(right);
11049         int offset = 0 ;        
11050         
11051         while (size--) {
11052             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11053             
11054             MOVA(l);
11055             pic16_emitcode("movx","@%s,a",rname);
11056
11057             if (size)
11058                 pic16_emitcode("inc","%s",rname);
11059
11060             offset++;
11061         }
11062     }
11063     
11064     /* now some housekeeping stuff */
11065     if (aop) {
11066         /* we had to allocate for this iCode */
11067         pic16_freeAsmop(NULL,aop,ic,TRUE);
11068     } else { 
11069         /* we did not allocate which means left
11070            already in a pointer register, then
11071            if size > 0 && this could be used again
11072            we have to point it back to where it 
11073            belongs */
11074         if (AOP_SIZE(right) > 1 &&
11075             !OP_SYMBOL(result)->remat &&
11076             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11077               ic->depth )) {
11078             int size = AOP_SIZE(right) - 1;
11079             while (size--)
11080                 pic16_emitcode("dec","%s",rname);
11081         }
11082     }
11083
11084     /* done */
11085     pic16_freeAsmop(right,NULL,ic,TRUE);
11086     
11087         
11088 }
11089
11090 /*-----------------------------------------------------------------*/
11091 /* genFarPointerSet - set value from far space                     */
11092 /*-----------------------------------------------------------------*/
11093 static void genFarPointerSet (operand *right,
11094                               operand *result, iCode *ic)
11095 {
11096     int size, offset ;
11097     sym_link *retype = getSpec(operandType(right));
11098
11099     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11100     pic16_aopOp(result,ic,FALSE);
11101
11102     /* if the operand is already in dptr 
11103     then we do nothing else we move the value to dptr */
11104     if (AOP_TYPE(result) != AOP_STR) {
11105         /* if this is remateriazable */
11106         if (AOP_TYPE(result) == AOP_IMMD)
11107             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11108         else { /* we need to get it byte by byte */
11109             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11110             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11111             if (options.model == MODEL_FLAT24)
11112             {
11113                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11114             }
11115         }
11116     }
11117     /* so dptr know contains the address */
11118     pic16_freeAsmop(result,NULL,ic,TRUE);
11119     pic16_aopOp(right,ic,FALSE);
11120
11121     /* if bit then unpack */
11122     if (IS_BITFIELD(retype)) 
11123         genPackBits(retype,result,right,"dptr",FPOINTER);
11124     else {
11125         size = AOP_SIZE(right);
11126         offset = 0 ;
11127
11128         while (size--) {
11129             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11130             MOVA(l);
11131             pic16_emitcode("movx","@dptr,a");
11132             if (size)
11133                 pic16_emitcode("inc","dptr");
11134         }
11135     }
11136
11137     pic16_freeAsmop(right,NULL,ic,TRUE);
11138 }
11139
11140 /*-----------------------------------------------------------------*/
11141 /* genGenPointerSet - set value from generic pointer space         */
11142 /*-----------------------------------------------------------------*/
11143 #if 0
11144 static void genGenPointerSet (operand *right,
11145                               operand *result, iCode *ic)
11146 {
11147         int i, size, offset, lit;
11148         sym_link *retype = getSpec(operandType(right));
11149
11150         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11151
11152         pic16_aopOp(result,ic,FALSE);
11153         pic16_aopOp(right,ic,FALSE);
11154         size = AOP_SIZE(right);
11155         offset = 0;
11156
11157         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11158
11159         /* if the operand is already in dptr 
11160                 then we do nothing else we move the value to dptr */
11161         if (AOP_TYPE(result) != AOP_STR) {
11162                 /* if this is remateriazable */
11163                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11164                 // WARNING: anythig until "else" is untested!
11165                 if (AOP_TYPE(result) == AOP_IMMD) {
11166                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11167                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11168                         // load FSR0 from immediate
11169                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11170                         offset = 0;
11171                         while(size--) {
11172                                 if(size) {
11173                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11174                                 } else {
11175                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11176                                 }
11177                                 offset++;
11178                         }
11179                         goto release;
11180                 }
11181                 else { /* we need to get it byte by byte */
11182                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11183                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11184
11185                         // set up FSR0 with address of result
11186                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11187                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11188
11189                         /* hack hack! see if this the FSR. If so don't load W */
11190                         if(AOP_TYPE(right) != AOP_ACC) {
11191
11192                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11193
11194                                 if(AOP_TYPE(right) == AOP_LIT)
11195                                 {
11196                                         // copy literal
11197                                         // note: pic16_popGet handles sign extension
11198                                         for(i=0;i<size;i++) {
11199                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11200                                                 if(i < size-1)
11201                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11202                                                 else
11203                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11204                                         }
11205                                 } else {
11206                                         // copy regs
11207
11208                                         for(i=0;i<size;i++) {
11209                                                 if(i < size-1)
11210                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11211                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11212                                                 else
11213                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11214                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11215                                         }
11216                                 }
11217                                 goto release;
11218                         } 
11219                         // right = ACC
11220                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11221                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11222                         goto release;
11223         } // if (AOP_TYPE(result) != AOP_IMMD)
11224
11225         } // if (AOP_TYPE(result) != AOP_STR)
11226         /* so dptr know contains the address */
11227
11228
11229         /* if bit then unpack */
11230         if (IS_BITFIELD(retype)) 
11231                 genPackBits(retype,result,right,"dptr",GPOINTER);
11232         else {
11233                 size = AOP_SIZE(right);
11234                 offset = 0 ;
11235
11236                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11237
11238                 // set up FSR0 with address of result
11239                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11240                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11241         
11242                 while (size--) {
11243                         if (AOP_TYPE(right) == AOP_LIT) {
11244                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11245                                 if (size) {
11246                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11247                                 } else {
11248                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11249                                 }
11250                         } else { // no literal
11251                                 if(size) {
11252                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11253                                 } else {
11254                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11255                                 }
11256                         }
11257                         offset++;
11258                 }
11259         }
11260
11261         release:
11262         pic16_freeAsmop(right,NULL,ic,TRUE);
11263         pic16_freeAsmop(result,NULL,ic,TRUE);
11264 }
11265 #endif
11266
11267 static void genGenPointerSet (operand *right,
11268                               operand *result, iCode *ic)
11269 {
11270   int size;
11271   sym_link *retype = getSpec(operandType(right));
11272   char fgptrput[32];
11273
11274     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11275
11276     pic16_aopOp(result,ic,FALSE);
11277     pic16_aopOp(right,ic,FALSE);
11278     size = AOP_SIZE(right);
11279
11280     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11281
11282
11283     /* if bit then unpack */
11284     if (IS_BITFIELD(retype)) {
11285 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11286       genPackBits(retype,result,right,"dptr",GPOINTER);
11287       goto release;
11288     }
11289
11290     size = AOP_SIZE(right);
11291
11292     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11293
11294
11295
11296     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11297
11298     /* value of right+0 is placed on stack, which will be retrieved
11299      * by the support function this restoring the stack. The important
11300      * thing is that there is no need to manually restore stack pointer
11301      * here */
11302     mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11303     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11304     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11305     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11306     
11307     /* load address to write to in WREG:FSR0H:FSR0L */
11308     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11309                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11310     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11311                                 pic16_popCopyReg(&pic16_pc_prodl)));
11312     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11313     
11314
11315     /* put code here */
11316     switch (size) {
11317       case 1: strcpy(fgptrput, "__gptrput1"); break;
11318       case 2: strcpy(fgptrput, "__gptrput2"); break;
11319       case 3: strcpy(fgptrput, "__gptrput3"); break;
11320       case 4: strcpy(fgptrput, "__gptrput4"); break;
11321       default:
11322         werror(W_POSSBUG2, __FILE__, __LINE__);
11323         abort();
11324     }
11325     
11326     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11327     
11328     {
11329       symbol *sym;
11330                   
11331         sym = newSymbol( fgptrput, 0 );
11332         strcpy(sym->rname, fgptrput);
11333         checkAddSym(&externs, sym);
11334     }
11335
11336 release:
11337     pic16_freeAsmop(right,NULL,ic,TRUE);
11338     pic16_freeAsmop(result,NULL,ic,TRUE);
11339 }
11340
11341 /*-----------------------------------------------------------------*/
11342 /* genPointerSet - stores the value into a pointer location        */
11343 /*-----------------------------------------------------------------*/
11344 static void genPointerSet (iCode *ic)
11345 {    
11346     operand *right, *result ;
11347     sym_link *type, *etype;
11348     int p_type;
11349
11350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11351
11352     right = IC_RIGHT(ic);
11353     result = IC_RESULT(ic) ;
11354
11355     /* depending on the type of pointer we need to
11356     move it to the correct pointer register */
11357     type = operandType(result);
11358     etype = getSpec(type);
11359     /* if left is of type of pointer then it is simple */
11360     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11361         p_type = DCL_TYPE(type);
11362     }
11363     else {
11364         /* we have to go by the storage class */
11365         p_type = PTR_TYPE(SPEC_OCLS(etype));
11366
11367 /*      if (SPEC_OCLS(etype)->codesp ) { */
11368 /*          p_type = CPOINTER ;  */
11369 /*      } */
11370 /*      else */
11371 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11372 /*              p_type = FPOINTER ; */
11373 /*          else */
11374 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11375 /*                  p_type = PPOINTER ; */
11376 /*              else */
11377 /*                  if (SPEC_OCLS(etype) == idata ) */
11378 /*                      p_type = IPOINTER ; */
11379 /*                  else */
11380 /*                      p_type = POINTER ; */
11381     }
11382
11383     /* now that we have the pointer type we assign
11384     the pointer values */
11385     switch (p_type) {
11386
11387     case POINTER:
11388     case IPOINTER:
11389         genNearPointerSet (right,result,ic);
11390         break;
11391
11392     case PPOINTER:
11393         genPagedPointerSet (right,result,ic);
11394         break;
11395
11396     case FPOINTER:
11397         genFarPointerSet (right,result,ic);
11398         break;
11399
11400     case GPOINTER:
11401         genGenPointerSet (right,result,ic);
11402         break;
11403
11404     default:
11405       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11406               "genPointerSet: illegal pointer type");
11407     }
11408 }
11409
11410 /*-----------------------------------------------------------------*/
11411 /* genIfx - generate code for Ifx statement                        */
11412 /*-----------------------------------------------------------------*/
11413 static void genIfx (iCode *ic, iCode *popIc)
11414 {
11415   operand *cond = IC_COND(ic);
11416   int isbit =0;
11417
11418   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11419
11420   pic16_aopOp(cond,ic,FALSE);
11421
11422   /* get the value into acc */
11423   if (AOP_TYPE(cond) != AOP_CRY)
11424     pic16_toBoolean(cond);
11425   else
11426     isbit = 1;
11427   /* the result is now in the accumulator */
11428   pic16_freeAsmop(cond,NULL,ic,TRUE);
11429
11430   /* if there was something to be popped then do it */
11431   if (popIc)
11432     genIpop(popIc);
11433
11434   /* if the condition is  a bit variable */
11435   if (isbit && IS_ITEMP(cond) && 
11436       SPIL_LOC(cond)) {
11437     genIfxJump(ic,SPIL_LOC(cond)->rname);
11438     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11439   }
11440   else {
11441     if (isbit && !IS_ITEMP(cond))
11442       genIfxJump(ic,OP_SYMBOL(cond)->rname);
11443     else
11444       genIfxJump(ic,"a");
11445   }
11446   ic->generated = 1;
11447
11448 }
11449
11450 /*-----------------------------------------------------------------*/
11451 /* genAddrOf - generates code for address of                       */
11452 /*-----------------------------------------------------------------*/
11453 static void genAddrOf (iCode *ic)
11454 {
11455   operand *result, *left;
11456   int size;
11457   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
11458   pCodeOp *pcop0, *pcop1, *pcop2;
11459
11460     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11461
11462     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
11463
11464     sym = OP_SYMBOL( IC_LEFT(ic) );
11465     
11466     if(sym->onStack) {
11467       /* get address of symbol on stack */
11468       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
11469 #if 0
11470       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
11471                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
11472 #endif
11473
11474       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11475                       pic16_popCopyReg(&pic16_pc_fsr2l),
11476                       pic16_popGet(AOP(result), 0)));
11477       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11478                       pic16_popCopyReg(&pic16_pc_fsr2h),
11479                       pic16_popGet(AOP(result), 1)));
11480       
11481       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
11482       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
11483       emitSKPNC;
11484       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
11485
11486       goto release;
11487     }
11488         
11489 //      if(pic16_debug_verbose) {
11490 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
11491 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
11492 //      }
11493         
11494     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
11495     size = AOP_SIZE(IC_RESULT(ic));
11496
11497
11498     /* Assume that what we want the address of is in data space
11499      * since there is no stack on the PIC, yet! -- VR */
11500   
11501     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11502     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11503     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11504         
11505     if (size == 3) {
11506       pic16_emitpcode(POC_MOVLW, pcop0);
11507       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11508       pic16_emitpcode(POC_MOVLW, pcop1);
11509       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11510       pic16_emitpcode(POC_MOVLW, pcop2);
11511       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11512     } else
11513     if (size == 2) {
11514       pic16_emitpcode(POC_MOVLW, pcop0);
11515       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11516       pic16_emitpcode(POC_MOVLW, pcop1);
11517     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11518     } else {
11519       pic16_emitpcode(POC_MOVLW, pcop0);
11520       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11521     }
11522
11523     pic16_freeAsmop(left, NULL, ic, FALSE);
11524 release:
11525     pic16_freeAsmop(result,NULL,ic,TRUE);
11526 }
11527
11528
11529 #if 0
11530 /*-----------------------------------------------------------------*/
11531 /* genFarFarAssign - assignment when both are in far space         */
11532 /*-----------------------------------------------------------------*/
11533 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
11534 {
11535     int size = AOP_SIZE(right);
11536     int offset = 0;
11537     char *l ;
11538     /* first push the right side on to the stack */
11539     while (size--) {
11540         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11541         MOVA(l);
11542         pic16_emitcode ("push","acc");
11543     }
11544     
11545     pic16_freeAsmop(right,NULL,ic,FALSE);
11546     /* now assign DPTR to result */
11547     pic16_aopOp(result,ic,FALSE);
11548     size = AOP_SIZE(result);
11549     while (size--) {
11550         pic16_emitcode ("pop","acc");
11551         pic16_aopPut(AOP(result),"a",--offset);
11552     }
11553     pic16_freeAsmop(result,NULL,ic,FALSE);
11554         
11555 }
11556 #endif
11557
11558 /*-----------------------------------------------------------------*/
11559 /* genAssign - generate code for assignment                        */
11560 /*-----------------------------------------------------------------*/
11561 static void genAssign (iCode *ic)
11562 {
11563   operand *result, *right;
11564   int size, offset,know_W;
11565   unsigned long lit = 0L;
11566
11567   result = IC_RESULT(ic);
11568   right  = IC_RIGHT(ic) ;
11569
11570   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11571   
11572   /* if they are the same */
11573   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
11574     return ;
11575
11576   /* reversed order operands are aopOp'ed so that result operand
11577    * is effective in case right is a stack symbol. This maneauver
11578    * allows to use the _G.resDirect flag later */
11579   pic16_aopOp(result,ic,TRUE);
11580   pic16_aopOp(right,ic,FALSE);
11581
11582   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11583
11584   /* if they are the same registers */
11585   if (pic16_sameRegs(AOP(right),AOP(result)))
11586     goto release;
11587
11588   /* if the result is a bit */
11589   if (AOP_TYPE(result) == AOP_CRY) {
11590     /* if the right size is a literal then
11591        we know what the value is */
11592     if (AOP_TYPE(right) == AOP_LIT) {
11593           
11594       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11595                   pic16_popGet(AOP(result),0));
11596
11597       if (((int) operandLitValue(right))) 
11598         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11599                        AOP(result)->aopu.aop_dir,
11600                        AOP(result)->aopu.aop_dir);
11601       else
11602         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11603                        AOP(result)->aopu.aop_dir,
11604                        AOP(result)->aopu.aop_dir);
11605       goto release;
11606     }
11607
11608     /* the right is also a bit variable */
11609     if (AOP_TYPE(right) == AOP_CRY) {
11610       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11611       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11612       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11613
11614       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11615                      AOP(result)->aopu.aop_dir,
11616                      AOP(result)->aopu.aop_dir);
11617       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
11618                      AOP(right)->aopu.aop_dir,
11619                      AOP(right)->aopu.aop_dir);
11620       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11621                      AOP(result)->aopu.aop_dir,
11622                      AOP(result)->aopu.aop_dir);
11623       goto release ;
11624     }
11625
11626     /* we need to or */
11627     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11628     pic16_toBoolean(right);
11629     emitSKPZ;
11630     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11631     //pic16_aopPut(AOP(result),"a",0);
11632     goto release ;
11633   }
11634
11635   /* bit variables done */
11636   /* general case */
11637   size = AOP_SIZE(result);
11638   offset = 0 ;
11639
11640   if(AOP_TYPE(right) == AOP_LIT) {
11641         if(!IS_FLOAT(operandType( right )))
11642                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11643         else {
11644            union {
11645               unsigned long lit_int;
11646               float lit_float;
11647             } info;
11648         
11649                 /* take care if literal is a float */
11650                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
11651                 lit = info.lit_int;
11652         }
11653   }
11654
11655 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
11656 //                      sizeof(unsigned long int), sizeof(float));
11657
11658   if(AOP_TYPE(right) != AOP_LIT
11659         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
11660         && !IS_FUNC(OP_SYM_TYPE(right))
11661         ) {
11662         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
11663 //      fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
11664
11665         // set up table pointer
11666         if( (AOP_TYPE(right) == AOP_PCODE)
11667                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
11668 //              || (AOP(right)->aopu.pcop->type == PO_DIR)
11669                 )
11670                 )
11671         {
11672 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
11673                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
11674                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11675                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
11676                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11677                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
11678                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11679         } else {
11680 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
11681                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
11682                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
11683                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
11684                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
11685                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
11686                                 pic16_popCopyReg(&pic16_pc_tblptru)));
11687         }
11688
11689         size = min(AOP_SIZE(right), AOP_SIZE(result));
11690         while(size--) {
11691                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11692                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
11693                         pic16_popGet(AOP(result),offset)));
11694                 offset++;
11695         }
11696
11697         if(AOP_SIZE(result) > AOP_SIZE(right)) {
11698                 size = AOP_SIZE(result) - AOP_SIZE(right);
11699                 while(size--) {
11700                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
11701                         offset++;
11702                 }
11703         }
11704         goto release;
11705   }
11706
11707
11708
11709 #if 0
11710 /* VR - What is this?! */
11711   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
11712     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11713     if(aopIdx(AOP(result),0) == 4) {
11714
11715       /* this is a workaround to save value of right into wreg too,
11716        * value of wreg is going to be used later */
11717       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11718       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11719       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11720       goto release;
11721     } else
11722 //      assert(0);
11723       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
11724   }
11725 #endif
11726
11727   know_W=-1;
11728   while (size--) {
11729   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
11730     if(AOP_TYPE(right) == AOP_LIT) {
11731       if(lit&0xff) {
11732         if(know_W != (lit&0xff))
11733           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
11734         know_W = lit&0xff;
11735         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11736       } else
11737         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11738
11739       lit >>= 8;
11740
11741     } else if (AOP_TYPE(right) == AOP_CRY) {
11742       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11743       if(offset == 0) {
11744         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
11745         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11746       }
11747     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
11748         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11749         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11750     } else {
11751       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11752
11753       if(!_G.resDirect)         /* use this aopForSym feature */
11754         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11755     }
11756             
11757     offset++;
11758   }
11759   
11760  release:
11761   pic16_freeAsmop (right,NULL,ic,FALSE);
11762   pic16_freeAsmop (result,NULL,ic,TRUE);
11763 }   
11764
11765 /*-----------------------------------------------------------------*/
11766 /* genJumpTab - generates code for jump table                       */
11767 /*-----------------------------------------------------------------*/
11768 static void genJumpTab (iCode *ic)
11769 {
11770     symbol *jtab;
11771     char *l;
11772
11773     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11774
11775     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11776     /* get the condition into accumulator */
11777     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11778     MOVA(l);
11779     /* multiply by three */
11780     pic16_emitcode("add","a,acc");
11781     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11782
11783     jtab = newiTempLabel(NULL);
11784     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11785     pic16_emitcode("jmp","@a+dptr");
11786     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11787
11788     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11789     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11790     emitSKPNC;
11791     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11792     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11793     pic16_emitpLabel(jtab->key);
11794
11795     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11796
11797     /* now generate the jump labels */
11798     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11799          jtab = setNextItem(IC_JTLABELS(ic))) {
11800         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11801         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11802         
11803     }
11804
11805 }
11806
11807 /*-----------------------------------------------------------------*/
11808 /* genMixedOperation - gen code for operators between mixed types  */
11809 /*-----------------------------------------------------------------*/
11810 /*
11811   TSD - Written for the PIC port - but this unfortunately is buggy.
11812   This routine is good in that it is able to efficiently promote 
11813   types to different (larger) sizes. Unfortunately, the temporary
11814   variables that are optimized out by this routine are sometimes
11815   used in other places. So until I know how to really parse the 
11816   iCode tree, I'm going to not be using this routine :(.
11817 */
11818 static int genMixedOperation (iCode *ic)
11819 {
11820 #if 0
11821   operand *result = IC_RESULT(ic);
11822   sym_link *ctype = operandType(IC_LEFT(ic));
11823   operand *right = IC_RIGHT(ic);
11824   int ret = 0;
11825   int big,small;
11826   int offset;
11827
11828   iCode *nextic;
11829   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11830
11831   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11832
11833   nextic = ic->next;
11834   if(!nextic)
11835     return 0;
11836
11837   nextright = IC_RIGHT(nextic);
11838   nextleft  = IC_LEFT(nextic);
11839   nextresult = IC_RESULT(nextic);
11840
11841   pic16_aopOp(right,ic,FALSE);
11842   pic16_aopOp(result,ic,FALSE);
11843   pic16_aopOp(nextright,  nextic, FALSE);
11844   pic16_aopOp(nextleft,   nextic, FALSE);
11845   pic16_aopOp(nextresult, nextic, FALSE);
11846
11847   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11848
11849     operand *t = right;
11850     right = nextright;
11851     nextright = t; 
11852
11853     pic16_emitcode(";remove right +","");
11854
11855   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11856 /*
11857     operand *t = right;
11858     right = nextleft;
11859     nextleft = t; 
11860 */
11861     pic16_emitcode(";remove left +","");
11862   } else
11863     return 0;
11864
11865   big = AOP_SIZE(nextleft);
11866   small = AOP_SIZE(nextright);
11867
11868   switch(nextic->op) {
11869
11870   case '+':
11871     pic16_emitcode(";optimize a +","");
11872     /* if unsigned or not an integral type */
11873     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11874       pic16_emitcode(";add a bit to something","");
11875     } else {
11876
11877       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11878
11879       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11880         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11881         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11882       } else
11883         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11884
11885       offset = 0;
11886       while(--big) {
11887
11888         offset++;
11889
11890         if(--small) {
11891           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11892             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11893             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11894           }
11895
11896           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11897           emitSKPNC;
11898           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11899                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11900                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11901           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11902           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11903
11904         } else {
11905           pic16_emitcode("rlf","known_zero,w");
11906
11907           /*
11908             if right is signed
11909               btfsc  right,7
11910                addlw ff
11911           */
11912           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11913             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11914             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11915           } else {
11916             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11917           }
11918         }
11919       }
11920       ret = 1;
11921     }
11922   }
11923   ret = 1;
11924
11925 release:
11926   pic16_freeAsmop(right,NULL,ic,TRUE);
11927   pic16_freeAsmop(result,NULL,ic,TRUE);
11928   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11929   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11930   if(ret)
11931     nextic->generated = 1;
11932
11933   return ret;
11934 #else
11935   return 0;
11936 #endif
11937 }
11938 /*-----------------------------------------------------------------*/
11939 /* genCast - gen code for casting                                  */
11940 /*-----------------------------------------------------------------*/
11941 static void genCast (iCode *ic)
11942 {
11943   operand *result = IC_RESULT(ic);
11944   sym_link *ctype = operandType(IC_LEFT(ic));
11945   sym_link *rtype = operandType(IC_RIGHT(ic));
11946   operand *right = IC_RIGHT(ic);
11947   int size, offset ;
11948
11949         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11950         /* if they are equivalent then do nothing */
11951         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11952                 return ;
11953
11954         pic16_aopOp(right,ic,FALSE) ;
11955         pic16_aopOp(result,ic,FALSE);
11956
11957         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11958
11959         /* if the result is a bit */
11960         if (AOP_TYPE(result) == AOP_CRY) {
11961         
11962                 /* if the right size is a literal then
11963                  * we know what the value is */
11964                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11965
11966                 if (AOP_TYPE(right) == AOP_LIT) {
11967                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11968                                 pic16_popGet(AOP(result),0));
11969
11970                         if (((int) operandLitValue(right))) 
11971                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11972                                         AOP(result)->aopu.aop_dir,
11973                                         AOP(result)->aopu.aop_dir);
11974                         else
11975                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11976                                         AOP(result)->aopu.aop_dir,
11977                                         AOP(result)->aopu.aop_dir);
11978                         goto release;
11979                 }
11980
11981                 /* the right is also a bit variable */
11982                 if (AOP_TYPE(right) == AOP_CRY) {
11983                         emitCLRC;
11984                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11985
11986                         pic16_emitcode("clrc","");
11987                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11988                                 AOP(right)->aopu.aop_dir,
11989                                 AOP(right)->aopu.aop_dir);
11990                         pic16_aopPut(AOP(result),"c",0);
11991                         goto release ;
11992                 }
11993
11994                 /* we need to or */
11995                 if (AOP_TYPE(right) == AOP_REG) {
11996                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11997                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11998                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11999                 }
12000                 pic16_toBoolean(right);
12001                 pic16_aopPut(AOP(result),"a",0);
12002                 goto release ;
12003         }
12004
12005         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12006           int offset = 1;
12007
12008                 size = AOP_SIZE(result);
12009
12010                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12011
12012                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12013                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12014                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12015
12016                 while (size--)
12017                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12018
12019                 goto release;
12020         }
12021
12022         /* if they are the same size : or less */
12023         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12024
12025                 /* if they are in the same place */
12026                 if (pic16_sameRegs(AOP(right),AOP(result)))
12027                         goto release;
12028
12029                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12030 #if 0
12031                 if (IS_PTR_CONST(rtype))
12032 #else
12033                 if (IS_CODEPTR(rtype))
12034 #endif
12035                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12036
12037 #if 0
12038                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12039 #else
12040                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12041 #endif
12042                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12043
12044 #if 0
12045                 if(AOP_TYPE(right) == AOP_IMMD) {
12046                   pCodeOp *pcop0, *pcop1, *pcop2;
12047                   symbol *sym = OP_SYMBOL( right );
12048
12049                         size = AOP_SIZE(result);
12050                         /* low */
12051                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12052                         /* high */
12053                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12054                         /* upper */
12055                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12056         
12057                         if (size == 3) {
12058                                 pic16_emitpcode(POC_MOVLW, pcop0);
12059                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12060                                 pic16_emitpcode(POC_MOVLW, pcop1);
12061                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12062                                 pic16_emitpcode(POC_MOVLW, pcop2);
12063                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12064                         } else
12065                         if (size == 2) {
12066                                 pic16_emitpcode(POC_MOVLW, pcop0);
12067                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12068                                 pic16_emitpcode(POC_MOVLW, pcop1);
12069                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12070                         } else {
12071                                 pic16_emitpcode(POC_MOVLW, pcop0);
12072                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12073                         }
12074                 } else
12075 #endif
12076                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12077                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12078                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12079                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12080                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12081                         if(AOP_SIZE(result) <2)
12082                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12083                 } else {
12084                         /* if they in different places then copy */
12085                         size = AOP_SIZE(result);
12086                         offset = 0 ;
12087                         while (size--) {
12088                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12089                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12090                                 offset++;
12091                         }
12092                 }
12093                 goto release;
12094         }
12095
12096         /* if the result is of type pointer */
12097         if (IS_PTR(ctype)) {
12098           int p_type;
12099           sym_link *type = operandType(right);
12100           sym_link *etype = getSpec(type);
12101
12102                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12103
12104                 /* pointer to generic pointer */
12105                 if (IS_GENPTR(ctype)) {
12106                   char *l = zero;
12107             
12108                         if (IS_PTR(type)) 
12109                                 p_type = DCL_TYPE(type);
12110                         else {
12111                 /* we have to go by the storage class */
12112                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12113
12114 /*              if (SPEC_OCLS(etype)->codesp )  */
12115 /*                  p_type = CPOINTER ;  */
12116 /*              else */
12117 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12118 /*                      p_type = FPOINTER ; */
12119 /*                  else */
12120 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12121 /*                          p_type = PPOINTER; */
12122 /*                      else */
12123 /*                          if (SPEC_OCLS(etype) == idata ) */
12124 /*                              p_type = IPOINTER ; */
12125 /*                          else */
12126 /*                              p_type = POINTER ; */
12127             }
12128                 
12129             /* the first two bytes are known */
12130       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12131             size = GPTRSIZE - 1; 
12132             offset = 0 ;
12133             while (size--) {
12134               if(offset < AOP_SIZE(right)) {
12135                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12136                 mov2f(AOP(result), AOP(right), offset);
12137 /*
12138                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12139                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12140                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12141                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12142                 } else { 
12143                   
12144                   pic16_aopPut(AOP(result),
12145                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12146                          offset);
12147                 }
12148 */
12149               } else 
12150                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12151               offset++;
12152             }
12153             /* the last byte depending on type */
12154             switch (p_type) {
12155             case IPOINTER:
12156             case POINTER:
12157                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12158                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12159 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12160                 break;
12161
12162             case CPOINTER:
12163                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12164                 break;
12165
12166             case FPOINTER:
12167               pic16_emitcode(";BUG!? ","%d",__LINE__);
12168                 l = one;
12169                 break;
12170             case PPOINTER:
12171               pic16_emitcode(";BUG!? ","%d",__LINE__);
12172                 l = "#0x03";
12173                 break;
12174
12175             case GPOINTER:
12176               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12177               break;
12178               
12179             default:
12180                 /* this should never happen */
12181                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12182                        "got unknown pointer type");
12183                 exit(1);
12184             }
12185             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12186             goto release ;
12187         }
12188         
12189         /* just copy the pointers */
12190         size = AOP_SIZE(result);
12191         offset = 0 ;
12192         while (size--) {
12193             pic16_aopPut(AOP(result),
12194                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12195                    offset);
12196             offset++;
12197         }
12198         goto release ;
12199     }
12200     
12201
12202
12203     /* so we now know that the size of destination is greater
12204     than the size of the source.
12205     Now, if the next iCode is an operator then we might be
12206     able to optimize the operation without performing a cast.
12207     */
12208     if(genMixedOperation(ic))
12209       goto release;
12210
12211     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12212     
12213     /* we move to result for the size of source */
12214     size = AOP_SIZE(right);
12215     offset = 0 ;
12216     while (size--) {
12217       mov2f(AOP(result), AOP(right), offset);
12218       offset++;
12219     }
12220
12221     /* now depending on the sign of the destination */
12222     size = AOP_SIZE(result) - AOP_SIZE(right);
12223     /* if unsigned or not an integral type */
12224     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12225       while (size--)
12226         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12227     } else {
12228       /* we need to extend the sign :( */
12229
12230       if(size == 1) {
12231         /* Save one instruction of casting char to int */
12232         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12233         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12234         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12235       } else {
12236         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12237
12238         if(offset)
12239           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12240         else
12241           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12242         
12243         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12244
12245         while (size--)
12246           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12247       }
12248     }
12249
12250 release:
12251     pic16_freeAsmop(right,NULL,ic,TRUE);
12252     pic16_freeAsmop(result,NULL,ic,TRUE);
12253
12254 }
12255
12256 /*-----------------------------------------------------------------*/
12257 /* genDjnz - generate decrement & jump if not zero instrucion      */
12258 /*-----------------------------------------------------------------*/
12259 static int genDjnz (iCode *ic, iCode *ifx)
12260 {
12261     symbol *lbl, *lbl1;
12262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12263
12264     if (!ifx)
12265         return 0;
12266     
12267     /* if the if condition has a false label
12268        then we cannot save */
12269     if (IC_FALSE(ifx))
12270         return 0;
12271
12272     /* if the minus is not of the form 
12273        a = a - 1 */
12274     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12275         !IS_OP_LITERAL(IC_RIGHT(ic)))
12276         return 0;
12277
12278     if (operandLitValue(IC_RIGHT(ic)) != 1)
12279         return 0;
12280
12281     /* if the size of this greater than one then no
12282        saving */
12283     if (getSize(operandType(IC_RESULT(ic))) > 1)
12284         return 0;
12285
12286     /* otherwise we can save BIG */
12287     lbl = newiTempLabel(NULL);
12288     lbl1= newiTempLabel(NULL);
12289
12290     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12291     
12292     if (IS_AOP_PREG(IC_RESULT(ic))) {
12293         pic16_emitcode("dec","%s",
12294                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12295         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12296         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12297     } else {    
12298
12299
12300       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12301       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12302
12303       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12304       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12305
12306     }
12307     
12308     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12309     ifx->generated = 1;
12310     return 1;
12311 }
12312
12313 /*-----------------------------------------------------------------*/
12314 /* genReceive - generate code for a receive iCode                  */
12315 /*-----------------------------------------------------------------*/
12316 static void genReceive (iCode *ic)
12317 {    
12318   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12319
12320 #if 0
12321   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12322         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12323 #endif
12324 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12325
12326   if (isOperandInFarSpace(IC_RESULT(ic))
12327       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12328           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12329
12330     int size = getSize(operandType(IC_RESULT(ic)));
12331     int offset =  pic16_fReturnSizePic - size;
12332
12333       assert( 0 );
12334       while (size--) {
12335         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12336                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12337                       offset++;
12338         }
12339
12340       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12341
12342       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12343       size = AOP_SIZE(IC_RESULT(ic));
12344       offset = 0;
12345       while (size--) {
12346         pic16_emitcode ("pop","acc");
12347         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12348       }
12349   } else {
12350     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12351
12352     _G.accInUse++;
12353     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12354     _G.accInUse--;
12355     assignResultValue(IC_RESULT(ic), 0);
12356   }
12357
12358   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12359 }
12360
12361 /*-----------------------------------------------------------------*/
12362 /* genDummyRead - generate code for dummy read of volatiles        */
12363 /*-----------------------------------------------------------------*/
12364 static void
12365 genDummyRead (iCode * ic)
12366 {
12367   pic16_emitcode ("; genDummyRead","");
12368   pic16_emitcode ("; not implemented","");
12369
12370   ic = ic;
12371 }
12372
12373 /*-----------------------------------------------------------------*/
12374 /* genpic16Code - generate code for pic16 based controllers        */
12375 /*-----------------------------------------------------------------*/
12376 /*
12377  * At this point, ralloc.c has gone through the iCode and attempted
12378  * to optimize in a way suitable for a PIC. Now we've got to generate
12379  * PIC instructions that correspond to the iCode.
12380  *
12381  * Once the instructions are generated, we'll pass through both the
12382  * peep hole optimizer and the pCode optimizer.
12383  *-----------------------------------------------------------------*/
12384
12385 void genpic16Code (iCode *lic)
12386 {
12387     iCode *ic;
12388     int cln = 0;
12389
12390     lineHead = lineCurr = NULL;
12391
12392     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12393     pic16_addpBlock(pb);
12394
12395 #if 0
12396     /* if debug information required */
12397     if (options.debug && currFunc) {
12398       if (currFunc) {
12399         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
12400       }
12401     }
12402 #endif
12403
12404     for (ic = lic ; ic ; ic = ic->next ) {
12405
12406       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
12407         if ( cln != ic->lineno ) {
12408             if ( options.debug ) {
12409               debugFile->writeCLine (ic);
12410             }
12411             
12412             if(!options.noCcodeInAsm) {
12413                 pic16_addpCode2pBlock(pb,
12414                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
12415                                 printCLine(ic->filename, ic->lineno)));
12416             }
12417
12418             cln = ic->lineno ;
12419         }
12420         
12421         if(options.iCodeInAsm) {
12422                 char *l;
12423                 /* insert here code to print iCode as comment */
12424                 l = Safe_strdup(printILine(ic));
12425                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
12426         }
12427         
12428         /* if the result is marked as
12429            spilt and rematerializable or code for
12430            this has already been generated then
12431            do nothing */
12432         if (resultRemat(ic) || ic->generated ) 
12433             continue ;
12434         
12435         /* depending on the operation */
12436         switch (ic->op) {
12437         case '!' :
12438             pic16_genNot(ic);
12439             break;
12440             
12441         case '~' :
12442             pic16_genCpl(ic);
12443             break;
12444             
12445         case UNARYMINUS:
12446             genUminus (ic);
12447             break;
12448             
12449         case IPUSH:
12450             genIpush (ic);
12451             break;
12452             
12453         case IPOP:
12454             /* IPOP happens only when trying to restore a 
12455                spilt live range, if there is an ifx statement
12456                following this pop then the if statement might
12457                be using some of the registers being popped which
12458                would destroy the contents of the register so
12459                we need to check for this condition and handle it */
12460             if (ic->next            && 
12461                 ic->next->op == IFX &&
12462                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
12463                 genIfx (ic->next,ic);
12464             else
12465                 genIpop (ic);
12466             break; 
12467             
12468         case CALL:
12469             genCall (ic);
12470             break;
12471             
12472         case PCALL:
12473             genPcall (ic);
12474             break;
12475             
12476         case FUNCTION:
12477             genFunction (ic);
12478             break;
12479             
12480         case ENDFUNCTION:
12481             genEndFunction (ic);
12482             break;
12483             
12484         case RETURN:
12485             genRet (ic);
12486             break;
12487             
12488         case LABEL:
12489             genLabel (ic);
12490             break;
12491             
12492         case GOTO:
12493             genGoto (ic);
12494             break;
12495             
12496         case '+' :
12497             pic16_genPlus (ic) ;
12498             break;
12499             
12500         case '-' :
12501             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
12502                 pic16_genMinus (ic);
12503             break;
12504             
12505         case '*' :
12506             genMult (ic);
12507             break;
12508             
12509         case '/' :
12510             genDiv (ic) ;
12511             break;
12512             
12513         case '%' :
12514             genMod (ic);
12515             break;
12516             
12517         case '>' :
12518             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
12519             break;
12520             
12521         case '<' :
12522             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
12523             break;
12524             
12525         case LE_OP:
12526         case GE_OP:
12527         case NE_OP:
12528             
12529             /* note these two are xlated by algebraic equivalence
12530                during parsing SDCC.y */
12531             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12532                    "got '>=' or '<=' shouldn't have come here");
12533             break;      
12534             
12535         case EQ_OP:
12536             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
12537             break;          
12538             
12539         case AND_OP:
12540             genAndOp (ic);
12541             break;
12542             
12543         case OR_OP:
12544             genOrOp (ic);
12545             break;
12546             
12547         case '^' :
12548             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
12549             break;
12550             
12551         case '|' :
12552                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
12553             break;
12554             
12555         case BITWISEAND:
12556             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
12557             break;
12558             
12559         case INLINEASM:
12560             genInline (ic);
12561             break;
12562             
12563         case RRC:
12564             genRRC (ic);
12565             break;
12566             
12567         case RLC:
12568             genRLC (ic);
12569             break;
12570             
12571         case GETHBIT:
12572             genGetHbit (ic);
12573             break;
12574             
12575         case LEFT_OP:
12576             genLeftShift (ic);
12577             break;
12578             
12579         case RIGHT_OP:
12580             genRightShift (ic);
12581             break;
12582             
12583         case GET_VALUE_AT_ADDRESS:
12584             genPointerGet(ic);
12585             break;
12586             
12587         case '=' :
12588             if (POINTER_SET(ic))
12589                 genPointerSet(ic);
12590             else
12591                 genAssign(ic);
12592             break;
12593             
12594         case IFX:
12595             genIfx (ic,NULL);
12596             break;
12597             
12598         case ADDRESS_OF:
12599             genAddrOf (ic);
12600             break;
12601             
12602         case JUMPTABLE:
12603             genJumpTab (ic);
12604             break;
12605             
12606         case CAST:
12607             genCast (ic);
12608             break;
12609             
12610         case RECEIVE:
12611             genReceive(ic);
12612             break;
12613             
12614         case SEND:
12615             addSet(&_G.sendSet,ic);
12616             /* create a reversed list of SEND iCodes */
12617 //            addSetHead(&_G.sendSet, ic);
12618             break;
12619
12620         case DUMMY_READ_VOLATILE:
12621           genDummyRead (ic);
12622           break;
12623
12624         default :
12625             ic = ic;
12626         }
12627     }
12628
12629
12630     /* now we are ready to call the
12631        peep hole optimizer */
12632     if (!options.nopeep) {
12633       peepHole (&lineHead);
12634     }
12635     /* now do the actual printing */
12636     printLine (lineHead, codeOutFile);
12637
12638 #ifdef PCODE_DEBUG
12639     DFPRINTF((stderr,"printing pBlock\n\n"));
12640     pic16_printpBlock(stdout,pb);
12641 #endif
12642
12643     return;
12644 }
12645