* device/lib/printf_large.c: removed inline assembly for portability and
[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,2005)
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 /* Set the following to 1 to enable the slower/bigger
51  * but more robust generic shifting routine (which also
52  * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
54
55 /* Set the following to 1 to enable the new
56  * stripped down genCmp version.
57  * This version should be easier to understand,
58  * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
60
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
141
142 static char *accUse[] = {"WREG"};
143
144 //static short rbank = -1;
145
146 static struct {
147     short r0Pushed;
148     short r1Pushed;
149     short fsr0Pushed;
150     short accInUse;
151     short inLine;
152     short debugLine;
153     short nRegsSaved;
154     short ipushRegs;
155     set *sendSet;
156     set *stackRegSet;
157     int usefastretfie;
158     bitVect *fregsUsed;                 /* registers used in function */
159     bitVect *sregsAlloc;
160     set *sregsAllocSet;                 /* registers used to store stack variables */
161     int stack_lat;                      /* stack offset latency */
162     int resDirect;
163     int useWreg;                        /* flag when WREG is used to pass function parameter */
164 } _G;
165
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
170
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
173
174 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
178
179 static  pBlock *pb;
180
181 /*-----------------------------------------------------------------*/
182 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
183 /*                 exponent of 2 is returned, otherwise -1 is      */
184 /*                 returned.                                       */
185 /* note that this is similar to the function `powof2' in SDCCsymt  */
186 /* if(n == 2^y)                                                    */
187 /*   return y;                                                     */
188 /* return -1;                                                      */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
191 {
192   if(num) {
193     if( (num & (num-1)) == 0) {
194       int nshifts = -1;
195       while(num) {
196         num>>=1;
197         nshifts++;
198       }
199       return nshifts;
200     }
201   }
202
203   return -1;
204 }
205
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
207 {
208   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
209                        line_no,
210                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
213                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
215                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216                        ((result) ? AOP_SIZE(result) : 0));
217 }
218
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
220 {
221
222   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
223                        line_no,
224                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
227                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
228                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
229                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
230
231 }
232
233 void pic16_emitpcomment (char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     va_start(ap,fmt);   
240
241     lb[0] = ';';
242     vsprintf(lb+1,fmt,ap);
243
244     while (isspace(*lbp)) lbp++;
245
246     if (lbp && *lbp) 
247         lineCurr = (lineCurr ?
248                     connectLine(lineCurr,newLineNode(lb)) :
249                     (lineHead = newLineNode(lb)));
250     lineCurr->isInline = _G.inLine;
251     lineCurr->isDebug  = _G.debugLine;
252
253     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
254     va_end(ap);
255
256 //      fprintf(stderr, "%s\n", lb);
257 }
258
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
260 {
261     va_list ap;
262     char lb[INITIAL_INLINEASM];  
263     char *lbp = lb;
264
265     if(!pic16_debug_verbose)
266       return;
267
268     va_start(ap,fmt);   
269
270     if (inst && *inst) {
271         if (fmt && *fmt)
272             sprintf(lb,"%s\t",inst);
273         else
274             sprintf(lb,"%s",inst);
275         vsprintf(lb+(strlen(lb)),fmt,ap);
276     }  else
277         vsprintf(lb,fmt,ap);
278
279     while (isspace(*lbp)) lbp++;
280
281     if (lbp && *lbp) 
282         lineCurr = (lineCurr ?
283                     connectLine(lineCurr,newLineNode(lb)) :
284                     (lineHead = newLineNode(lb)));
285     lineCurr->isInline = _G.inLine;
286     lineCurr->isDebug  = _G.debugLine;
287
288     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
289     va_end(ap);
290
291 //      fprintf(stderr, "%s\n", lb);
292 }
293
294
295
296 void pic16_emitpLabel(int key)
297 {
298   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
299 }
300
301 void pic16_emitpLabelFORCE(int key)
302 {
303   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
304 }
305
306 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
307 {
308
309   if(pcop)
310     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
311   else
312     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
313 }
314
315 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
316 {
317   if(pcop)
318     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
319   else
320     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
321 }
322   
323 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
324 {
325
326   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
327
328 }
329
330
331 #if 1
332 #define pic16_emitcode  DEBUGpic16_emitcode
333 #else
334 /*-----------------------------------------------------------------*/
335 /* pic16_emitcode - writes the code into a file : for now it is simple    */
336 /*-----------------------------------------------------------------*/
337 void pic16_emitcode (char *inst,char *fmt, ...)
338 {
339     va_list ap;
340     char lb[INITIAL_INLINEASM];  
341     char *lbp = lb;
342
343     va_start(ap,fmt);   
344
345     if (inst && *inst) {
346         if (fmt && *fmt)
347             sprintf(lb,"%s\t",inst);
348         else
349             sprintf(lb,"%s",inst);
350         vsprintf(lb+(strlen(lb)),fmt,ap);
351     }  else
352         vsprintf(lb,fmt,ap);
353
354     while (isspace(*lbp)) lbp++;
355
356     if (lbp && *lbp) 
357         lineCurr = (lineCurr ?
358                     connectLine(lineCurr,newLineNode(lb)) :
359                     (lineHead = newLineNode(lb)));
360     lineCurr->isInline = _G.inLine;
361     lineCurr->isDebug  = _G.debugLine;
362
363 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
364
365 //    if(pic16_debug_verbose)
366 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
367
368     va_end(ap);
369 }
370 #endif
371
372
373 /*-----------------------------------------------------------------*/
374 /* pic16_emitDebuggerSymbol - associate the current code location  */
375 /*   with a debugger symbol                                        */
376 /*-----------------------------------------------------------------*/
377 void
378 pic16_emitDebuggerSymbol (char * debugSym)
379 {
380   _G.debugLine = 1;
381   pic16_emitcode (";", "%s ==.", debugSym);
382   _G.debugLine = 0;
383 }
384
385
386 /*-----------------------------------------------------------------*/
387 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
388 /*-----------------------------------------------------------------*/
389 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
390 {
391 //    bool r0iu = FALSE , r1iu = FALSE;
392 //    bool r0ou = FALSE , r1ou = FALSE;
393     bool fsr0iu = FALSE, fsr0ou;
394     bool fsr2iu = FALSE, fsr2ou;
395     
396     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
397
398     
399     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
400     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
401     
402     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
403     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
404
405     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
406         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
407         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
408     }
409
410     if(!fsr0iu && !fsr0ou) {
411         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
412         (*aopp)->type = AOP_FSR0;
413
414         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
415         
416       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
417     }
418
419 #if 0
420     /* no usage of FSR2 */
421     if(!fsr2iu && !fsr2ou) {
422         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
423         (*aopp)->type = AOP_FSR2;
424
425       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
426     }
427 #endif
428         
429     /* now we know they both have usage */
430     /* if fsr0 not used in this instruction */
431     if (!fsr0iu) {
432         if (!_G.fsr0Pushed) {
433                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
434                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
435                 _G.fsr0Pushed++;
436         }
437
438         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
439         (*aopp)->type = AOP_FSR0;
440
441 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
442
443       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
444     }
445         
446
447     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
448     assert( 0 );
449
450     return NULL;
451 #if 0
452     /* the logic: if r0 & r1 used in the instruction
453     then we are in trouble otherwise */
454
455     /* first check if r0 & r1 are used by this
456     instruction, in which case we are in trouble */
457     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
458         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
459     {
460         goto endOfWorld;      
461     }
462
463     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
464     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
465
466     /* if no usage of r0 then return it */
467     if (!r0iu && !r0ou) {
468         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
469         (*aopp)->type = AOP_R0; 
470         
471         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
472     }
473
474     /* if no usage of r1 then return it */
475     if (!r1iu && !r1ou) {
476         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477         (*aopp)->type = AOP_R1;
478
479         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
480     }    
481
482     /* now we know they both have usage */
483     /* if r0 not used in this instruction */
484     if (!r0iu) {
485         /* push it if not already pushed */
486         if (!_G.r0Pushed) {
487           //pic16_emitcode ("push","%s",
488           //          pic16_regWithIdx(R0_IDX)->dname);
489             _G.r0Pushed++ ;
490         }
491         
492         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
493         (*aopp)->type = AOP_R0;
494
495         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
496     }
497
498     /* if r1 not used then */
499
500     if (!r1iu) {
501         /* push it if not already pushed */
502         if (!_G.r1Pushed) {
503           //pic16_emitcode ("push","%s",
504           //          pic16_regWithIdx(R1_IDX)->dname);
505             _G.r1Pushed++ ;
506         }
507         
508         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
509         (*aopp)->type = AOP_R1;
510         return pic16_regWithIdx(R1_IDX);
511     }
512
513 endOfWorld :
514     /* I said end of world but not quite end of world yet */
515     /* if this is a result then we can push it on the stack*/
516     if (result) {
517         (*aopp)->type = AOP_STK;    
518         return NULL;
519     }
520
521     /* other wise this is true end of the world */
522     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
523            "getFreePtr should never reach here");
524     exit(0);
525 #endif
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* newAsmop - creates a new asmOp                                  */
530 /*-----------------------------------------------------------------*/
531 static asmop *newAsmop (short type)
532 {
533     asmop *aop;
534
535     aop = Safe_calloc(1,sizeof(asmop));
536     aop->type = type;
537     return aop;
538 }
539
540 static void genSetDPTR(int n)
541 {
542     if (!n)
543     {
544         pic16_emitcode(";", "Select standard DPTR");
545         pic16_emitcode("mov", "dps, #0x00");
546     }
547     else
548     {
549         pic16_emitcode(";", "Select alternate DPTR");
550         pic16_emitcode("mov", "dps, #0x01");
551     }
552 }
553
554 /*-----------------------------------------------------------------*/
555 /* resolveIfx - converts an iCode ifx into a form more useful for  */
556 /*              generating code                                    */
557 /*-----------------------------------------------------------------*/
558 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
559 {
560   FENTRY2;
561   
562 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
563
564   if(!resIfx) 
565     return;
566
567
568   resIfx->condition = 1;    /* assume that the ifx is true */
569   resIfx->generated = 0;    /* indicate that the ifx has not been used */
570
571   if(!ifx) {
572     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
573
574 #if 1
575     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
576                         __FUNCTION__,__LINE__,resIfx->lbl->key);
577 #endif
578
579   } else {
580     if(IC_TRUE(ifx)) {
581       resIfx->lbl = IC_TRUE(ifx);
582     } else {
583       resIfx->lbl = IC_FALSE(ifx);
584       resIfx->condition = 0;
585     }
586
587 #if 1
588     if(IC_TRUE(ifx)) 
589       DEBUGpic16_emitcode("; +++","ifx true is non-null");
590     else
591       DEBUGpic16_emitcode("; +++","ifx true is null");
592     if(IC_FALSE(ifx)) 
593       DEBUGpic16_emitcode("; +++","ifx false is non-null");
594     else
595       DEBUGpic16_emitcode("; +++","ifx false is null");
596 #endif
597   }
598
599   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
600
601 }
602 #if 0
603 /*-----------------------------------------------------------------*/
604 /* pointerCode - returns the code for a pointer type               */
605 /*-----------------------------------------------------------------*/
606 static int pointerCode (sym_link *etype)
607 {
608
609     return PTR_TYPE(SPEC_OCLS(etype));
610
611 }
612 #endif
613
614 /*-----------------------------------------------------------------*/
615 /* aopForSym - for a true symbol                                   */
616 /*-----------------------------------------------------------------*/
617 static asmop *aopForSym (iCode *ic, operand *op, bool result)
618 {
619     symbol *sym=OP_SYMBOL(op);
620     asmop *aop;
621     memmap *space= SPEC_OCLS(sym->etype);
622
623     FENTRY2;
624     
625     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
626     
627 //    sym = OP_SYMBOL(op);
628
629     /* if already has one */
630     if (sym->aop) {
631             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
632         return sym->aop;
633     }
634
635 #if 0
636     /* if symbol was initially placed onStack then we must re-place it
637      * to direct memory, since pic16 does not have a specific stack */
638     if(sym->onStack) {
639         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
640     }
641 #endif
642
643
644 #if 0
645     if(sym->iaccess) {
646       if(space->paged) {
647         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
648
649         sym->aop = aop = newAsmop (AOP_PAGED);
650         aop->aopu.aop_dir = sym->rname ;
651         aop->size = getSize(sym->type);
652         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
653         pic16_allocDirReg( IC_LEFT(ic) );
654         return aop;
655       }
656       assert( 0 );
657     }
658 #endif
659     
660 #if 1
661     /* assign depending on the storage class */
662     /* if it is on the stack or indirectly addressable */
663     /* space we need to assign either r0 or r1 to it   */    
664     if (sym->onStack)   // || sym->iaccess)
665     {
666       pCodeOp *pcop[4];
667       int i;
668       
669         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
670                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
671         
672         /* acquire a temporary register -- it is saved in function */
673
674         sym->aop = aop = newAsmop(AOP_STA);
675         aop->aopu.stk.stk = sym->stack;
676         aop->size = getSize(sym->type);
677
678
679         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
680         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
681           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
682           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
683           
684           for(i=0;i<aop->size;i++)
685             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
686             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
687         } else
688         if(1 && ic->op == SEND) {
689
690           /* if SEND do the send here */
691           _G.resDirect = 1;
692         } else {
693           for(i=0;i<aop->size;i++) {
694             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
695             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
696           }
697         }
698
699
700 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
701
702 #if 1
703         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
704
705         // we do not need to load the value if it is to be defined...
706         if (result) return aop;
707
708         if(_G.accInUse) {
709                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
710         }
711         
712         for(i=0;i<aop->size;i++) {
713
714           /* initialise for stack access via frame pointer */
715           // operands on stack are accessible via "FSR2 + index" with index
716           // starting at 2 for arguments and growing from 0 downwards for
717           // local variables (index == 0 is not assigned so we add one here)
718           {
719             int soffs = sym->stack;
720             if (soffs <= 0) {
721               assert (soffs < 0);
722               soffs++;
723             } // if
724
725             if(1 && ic->op == SEND) {
726               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
727               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
728                     pic16_popCopyReg( pic16_frame_plusw ),
729                     pic16_popCopyReg(pic16_stack_postdec )));
730             } else {
731               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
732               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
733                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
734             }
735           }
736         }
737         
738         if(_G.accInUse) {
739                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
740         }
741         
742         return (aop);
743 #endif
744
745 #if 0
746         /* now assign the address of the variable to 
747         the pointer register */
748         if (aop->type != AOP_STK) {
749
750             if (sym->onStack) {
751                     if ( _G.accInUse )
752                         pic16_emitcode("push","acc");
753
754                     pic16_emitcode("mov","a,_bp");
755                     pic16_emitcode("add","a,#0x%02x",
756                              ((sym->stack < 0) ?
757                               ((char)(sym->stack - _G.nRegsSaved )) :
758                               ((char)sym->stack)) & 0xff);
759                     pic16_emitcode("mov","%s,a",
760                              aop->aopu.aop_ptr->name);
761
762                     if ( _G.accInUse )
763                         pic16_emitcode("pop","acc");
764             } else
765                 pic16_emitcode("mov","%s,#%s",
766                          aop->aopu.aop_ptr->name,
767                          sym->rname);
768             aop->paged = space->paged;
769         } else
770             aop->aopu.aop_stk = sym->stack;
771         return aop;
772 #endif
773
774     }
775 #endif
776
777 #if 0
778     if (sym->onStack && options.stack10bit)
779     {
780         /* It's on the 10 bit stack, which is located in
781          * far data space.
782          */
783          
784       //DEBUGpic16_emitcode(";","%d",__LINE__);
785
786         if ( _G.accInUse )
787                 pic16_emitcode("push","acc");
788
789         pic16_emitcode("mov","a,_bp");
790         pic16_emitcode("add","a,#0x%02x",
791                  ((sym->stack < 0) ?
792                    ((char)(sym->stack - _G.nRegsSaved )) :
793                    ((char)sym->stack)) & 0xff);
794         
795         genSetDPTR(1);
796         pic16_emitcode ("mov","dpx1,#0x40");
797         pic16_emitcode ("mov","dph1,#0x00");
798         pic16_emitcode ("mov","dpl1, a");
799         genSetDPTR(0);
800         
801         if ( _G.accInUse )
802             pic16_emitcode("pop","acc");
803             
804         sym->aop = aop = newAsmop(AOP_DPTR2);
805         aop->size = getSize(sym->type); 
806         return aop;
807     }
808 #endif
809
810 #if 1
811     /* special case for a function */
812     if (IS_FUNC(sym->type)) {   
813         sym->aop = aop = newAsmop(AOP_PCODE);
814         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
815         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
816         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
817         PCOI(aop->aopu.pcop)->index = 0;
818         aop->size = FPTRSIZE; 
819         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
820         return aop;
821     }
822 #endif
823
824
825
826     //DEBUGpic16_emitcode(";","%d",__LINE__);
827     /* if in bit space */
828     if (IN_BITSPACE(space)) {
829         sym->aop = aop = newAsmop (AOP_CRY);
830         aop->aopu.aop_dir = sym->rname ;
831         aop->size = getSize(sym->type);
832         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
833         return aop;
834     }
835     /* if it is in direct space */
836     if (IN_DIRSPACE(space)) {
837         sym->aop = aop = newAsmop (AOP_DIR);
838         aop->aopu.aop_dir = sym->rname ;
839         aop->size = getSize(sym->type);
840         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841         pic16_allocDirReg( IC_LEFT(ic) );
842         return aop;
843     }
844
845
846     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
847         sym->aop = aop = newAsmop (AOP_DIR);
848         aop->aopu.aop_dir = sym->rname ;
849         aop->size = getSize(sym->type);
850         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851         pic16_allocDirReg( IC_LEFT(ic) );
852         return aop;
853     }
854
855
856     /* only remaining is far space */
857     sym->aop = aop = newAsmop(AOP_PCODE);
858
859 /* change the next if to 1 to revert to good old immediate code */
860         if(IN_CODESPACE(space)) {
861                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
862                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
863                 PCOI(aop->aopu.pcop)->index = 0;
864         } else {
865                 /* try to allocate via direct register */
866                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
867 //              aop->size = getSize( sym->type );
868         }
869
870         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
871                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
872
873 #if 0
874         if(!pic16_allocDirReg (IC_LEFT(ic)))
875                 return NULL;
876 #endif
877
878         if(IN_DIRSPACE( space ))
879                 aop->size = PTRSIZE;
880         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
881                 aop->size = FPTRSIZE;
882         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
883         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
884         else if(sym->onStack) {
885                 aop->size = PTRSIZE;
886         } else {
887           if(SPEC_SCLS(sym->etype) == S_PDATA) {
888             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
889             aop->size = FPTRSIZE;
890           } else
891                 assert( 0 );
892         }
893
894     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
895
896     /* if it is in code space */
897     if (IN_CODESPACE(space))
898         aop->code = 1;
899
900     return aop;     
901 }
902
903 /*-----------------------------------------------------------------*/
904 /* aopForRemat - rematerialzes an object                           */
905 /*-----------------------------------------------------------------*/
906 static asmop *aopForRemat (operand *op) // x symbol *sym)
907 {
908   symbol *sym = OP_SYMBOL(op);
909   operand *refop;
910   iCode *ic = NULL, *oldic;
911   asmop *aop = newAsmop(AOP_PCODE);
912   int val = 0;
913   int offset = 0;
914   int viaimmd=0;
915
916     FENTRY2;
917     
918         ic = sym->rematiCode;
919
920         if(IS_OP_POINTER(op)) {
921                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
922         }
923
924         for (;;) {
925                 oldic = ic;
926
927 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
928         
929                 if (ic->op == '+') {
930                         val += (int) operandLitValue(IC_RIGHT(ic));
931                 } else if (ic->op == '-') {
932                         val -= (int) operandLitValue(IC_RIGHT(ic));
933                 } else
934                         break;
935                 
936                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
937         }
938
939         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
940         refop = IC_LEFT(ic);
941
942         if(!op->isaddr)viaimmd++; else viaimmd=0;
943                 
944 /* set the following if to 1 to revert to good old immediate code */
945         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
946                 || viaimmd) {
947
948                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
949
950                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
951
952 #if 0
953                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
954 #else
955                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
956 #endif
957
958                 PCOI(aop->aopu.pcop)->index = val;
959                 
960                 aop->size = getSize( sym->type );
961         } else {
962                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
963
964                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
965                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
966
967                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
968         }
969
970
971         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
972                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
973 #if 0
974                 val, IS_PTR_CONST(operandType(op)));
975 #else
976                 val, IS_CODEPTR(operandType(op)));
977 #endif
978
979 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
980
981         pic16_allocDirReg (IC_LEFT(ic));
982
983         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
984                 aop->code = 1;
985
986   return aop;        
987 }
988
989 #if 0
990 static int aopIdx (asmop *aop, int offset)
991 {
992   if(!aop)
993     return -1;
994
995   if(aop->type !=  AOP_REG)
996     return -2;
997         
998   return aop->aopu.aop_reg[offset]->rIdx;
999
1000 }
1001 #endif
1002
1003 /*-----------------------------------------------------------------*/
1004 /* regsInCommon - two operands have some registers in common       */
1005 /*-----------------------------------------------------------------*/
1006 static bool regsInCommon (operand *op1, operand *op2)
1007 {
1008     symbol *sym1, *sym2;
1009     int i;
1010
1011     /* if they have registers in common */
1012     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1013         return FALSE ;
1014
1015     sym1 = OP_SYMBOL(op1);
1016     sym2 = OP_SYMBOL(op2);
1017
1018     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1019         return FALSE ;
1020
1021     for (i = 0 ; i < sym1->nRegs ; i++) {
1022         int j;
1023         if (!sym1->regs[i])
1024             continue ;
1025
1026         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1027             if (!sym2->regs[j])
1028                 continue ;
1029
1030             if (sym2->regs[j] == sym1->regs[i])
1031                 return TRUE ;
1032         }
1033     }
1034
1035     return FALSE ;
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* operandsEqu - equivalent                                        */
1040 /*-----------------------------------------------------------------*/
1041 static bool operandsEqu ( operand *op1, operand *op2)
1042 {
1043     symbol *sym1, *sym2;
1044
1045     /* if they not symbols */
1046     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1047         return FALSE;
1048
1049     sym1 = OP_SYMBOL(op1);
1050     sym2 = OP_SYMBOL(op2);
1051
1052     /* if both are itemps & one is spilt
1053        and the other is not then false */
1054     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1055         sym1->isspilt != sym2->isspilt )
1056         return FALSE ;
1057
1058     /* if they are the same */
1059     if (sym1 == sym2)
1060         return TRUE ;
1061
1062     if (sym1->rname[0] && sym2->rname[0]
1063         && strcmp (sym1->rname, sym2->rname) == 0)
1064         return TRUE;
1065
1066
1067     /* if left is a tmp & right is not */
1068     if (IS_ITEMP(op1)  && 
1069         !IS_ITEMP(op2) &&
1070         sym1->isspilt  &&
1071         (sym1->usl.spillLoc == sym2))
1072         return TRUE;
1073
1074     if (IS_ITEMP(op2)  && 
1075         !IS_ITEMP(op1) &&
1076         sym2->isspilt  &&
1077         sym1->level > 0 &&
1078         (sym2->usl.spillLoc == sym1))
1079         return TRUE ;
1080
1081     return FALSE ;
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* pic16_sameRegs - two asmops have the same registers                   */
1086 /*-----------------------------------------------------------------*/
1087 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1088 {
1089     int i;
1090
1091     if (aop1 == aop2)
1092         return TRUE ;
1093
1094     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1095                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1096
1097     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1098
1099     if (aop1->type != AOP_REG ||
1100         aop2->type != AOP_REG )
1101         return FALSE ;
1102
1103     /* This is a bit too restrictive if one is a subset of the other...
1104     if (aop1->size != aop2->size )
1105         return FALSE ;
1106     */
1107
1108     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1109 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1110
1111 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1112         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1113             return FALSE ;
1114     }
1115
1116     return TRUE ;
1117 }
1118
1119 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1120 {
1121     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1122                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1123
1124     if(aop1 == aop2)return TRUE;
1125     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1126       
1127       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1128     
1129   return TRUE;
1130 }
1131
1132
1133 /*-----------------------------------------------------------------*/
1134 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1135 /*-----------------------------------------------------------------*/
1136 void pic16_aopOp (operand *op, iCode *ic, bool result)
1137 {
1138     asmop *aop;
1139     symbol *sym;
1140     int i;
1141
1142     if (!op)
1143         return ;
1144
1145     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1146
1147     /* if this a literal */
1148     if (IS_OP_LITERAL(op)) {
1149         op->aop = aop = newAsmop(AOP_LIT);
1150         aop->aopu.aop_lit = op->operand.valOperand;
1151         aop->size = getSize(operandType(op));
1152         return;
1153     }
1154
1155     {
1156       sym_link *type = operandType(op);
1157 #if 0
1158       if(IS_PTR_CONST(type))
1159 #else
1160       if(IS_CODEPTR(type))
1161 #endif
1162         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1163     }
1164
1165     /* if already has a asmop then continue */
1166     if (op->aop)
1167         return ;
1168
1169     /* if the underlying symbol has a aop */
1170     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1171       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1172         op->aop = OP_SYMBOL(op)->aop;
1173         return;
1174     }
1175
1176     /* if this is a true symbol */
1177     if (IS_TRUE_SYMOP(op)) {    
1178         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1179       op->aop = aopForSym(ic, op, result);
1180       return ;
1181     }
1182
1183     /* this is a temporary : this has
1184     only four choices :
1185     a) register
1186     b) spillocation
1187     c) rematerialize 
1188     d) conditional   
1189     e) can be a return use only */
1190
1191     sym = OP_SYMBOL(op);
1192
1193     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1194     /* if the type is a conditional */
1195     if (sym->regType == REG_CND) {
1196         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1197         aop->size = 0;
1198         return;
1199     }
1200
1201     /* if it is spilt then two situations
1202     a) is rematerialize 
1203     b) has a spill location */
1204     if (sym->isspilt || sym->nRegs == 0) {
1205
1206 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1207       DEBUGpic16_emitcode(";","%d",__LINE__);
1208         /* rematerialize it NOW */
1209         if (sym->remat) {
1210
1211             sym->aop = op->aop = aop = aopForRemat (op);
1212 //            aop->size = getSize(sym->type);
1213 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1214             return;
1215         }
1216
1217 #if 1
1218         if (sym->accuse) {
1219             int i;
1220             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1221             aop->size = getSize(sym->type);
1222             for ( i = 0 ; i < 1 ; i++ ) {
1223                 aop->aopu.aop_str[i] = accUse[i];
1224 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1225             }
1226             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1227             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1228             return;  
1229         }
1230 #endif
1231
1232 #if 1
1233         if (sym->ruonly) {
1234           /*
1235           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1236           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1237           //pic16_allocDirReg (IC_LEFT(ic));
1238           aop->size = getSize(sym->type);
1239           */
1240
1241           unsigned i;
1242
1243           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1244           aop->size = getSize(sym->type);
1245           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1246             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1247
1248           DEBUGpic16_emitcode(";","%d",__LINE__);
1249           return;
1250         }
1251 #endif
1252         /* else spill location  */
1253         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1254             /* force a new aop if sizes differ */
1255             sym->usl.spillLoc->aop = NULL;
1256         }
1257
1258 #if 0
1259         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1260                             __FUNCTION__,__LINE__,
1261                             sym->usl.spillLoc->rname,
1262                             sym->rname, sym->usl.spillLoc->offset);
1263 #endif
1264
1265         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1266         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1267         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1268           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1269                                                   getSize(sym->type), 
1270                                                   sym->usl.spillLoc->offset, op);
1271         } else {
1272           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1273           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1274           assert (getSize(sym->type) <= 1);
1275           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1276         }
1277         aop->size = getSize(sym->type);
1278
1279         return;
1280     }
1281
1282     {
1283       sym_link *type = operandType(op);
1284 #if 0
1285       if(IS_PTR_CONST(type)) 
1286 #else
1287       if(IS_CODEPTR(type)) 
1288 #endif
1289         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1290     }
1291
1292     /* must be in a register */
1293     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1294     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1295     aop->size = sym->nRegs;
1296     for ( i = 0 ; i < sym->nRegs ;i++)
1297         aop->aopu.aop_reg[i] = sym->regs[i];
1298 }
1299
1300 /*-----------------------------------------------------------------*/
1301 /* pic16_freeAsmop - free up the asmop given to an operand               */
1302 /*----------------------------------------------------------------*/
1303 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1304 {   
1305     asmop *aop ;
1306
1307     if (!op)
1308         aop = aaop;
1309     else 
1310         aop = op->aop;
1311
1312     if (!aop)
1313         return ;
1314
1315     if (aop->freed)
1316         goto dealloc; 
1317
1318     aop->freed = 1;
1319
1320     /* depending on the asmop type only three cases need work AOP_RO
1321        , AOP_R1 && AOP_STK */
1322 #if 1
1323     switch (aop->type) {
1324         case AOP_FSR0 :
1325             if (_G.fsr0Pushed ) {
1326                 if (pop) {
1327                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1328                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1329 //                    pic16_emitcode ("pop","ar0");
1330                     _G.fsr0Pushed--;
1331                 }
1332             }
1333             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1334             break;
1335
1336         case AOP_FSR2 :
1337             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1338             break;
1339
1340         case AOP_R0 :
1341             if (_G.r0Pushed ) {
1342                 if (pop) {
1343                     pic16_emitcode ("pop","ar0");     
1344                     _G.r0Pushed--;
1345                 }
1346             }
1347             bitVectUnSetBit(ic->rUsed,R0_IDX);
1348             break;
1349
1350         case AOP_R1 :
1351             if (_G.r1Pushed ) {
1352                 if (pop) {
1353                     pic16_emitcode ("pop","ar1");
1354                     _G.r1Pushed--;
1355                 }
1356             }
1357             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1358             break;
1359
1360         case AOP_STA:
1361           {
1362             int i;
1363
1364               /* we must store the result on stack */
1365               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1366                 // operands on stack are accessible via "FSR2 + index" with index
1367                 // starting at 2 for arguments and growing from 0 downwards for
1368                 // local variables (index == 0 is not assigned so we add one here)
1369                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1370                 if (soffs <= 0) {
1371                   assert (soffs < 0);
1372                   soffs++;
1373                 } // if
1374                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1375                 for(i=0;i<aop->size;i++) {
1376                   /* initialise for stack access via frame pointer */
1377                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1378                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1379                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1380                 }
1381         
1382                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1383               }
1384
1385               if(!_G.resDirect) {
1386                 for(i=0;i<aop->size;i++) {
1387                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1388
1389                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1390                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1391                 }
1392                   
1393               }
1394               _G.resDirect = 0;
1395           }
1396           break;
1397 #if 0
1398         case AOP_STK :
1399         {
1400             int sz = aop->size;    
1401             int stk = aop->aopu.aop_stk + aop->size;
1402             bitVectUnSetBit(ic->rUsed,R0_IDX);
1403             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1404
1405             getFreePtr(ic,&aop,FALSE);
1406             
1407             if (options.stack10bit)
1408             {
1409                 /* I'm not sure what to do here yet... */
1410                 /* #STUB */
1411                 fprintf(stderr, 
1412                         "*** Warning: probably generating bad code for "
1413                         "10 bit stack mode.\n");
1414             }
1415             
1416             if (stk) {
1417                 pic16_emitcode ("mov","a,_bp");
1418                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1419                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1420             } else {
1421                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1422             }
1423
1424             while (sz--) {
1425                 pic16_emitcode("pop","acc");
1426                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1427                 if (!sz) break;
1428                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1429             }
1430             op->aop = aop;
1431             pic16_freeAsmop(op,NULL,ic,TRUE);
1432             if (_G.r0Pushed) {
1433                 pic16_emitcode("pop","ar0");
1434                 _G.r0Pushed--;
1435             }
1436
1437             if (_G.r1Pushed) {
1438                 pic16_emitcode("pop","ar1");
1439                 _G.r1Pushed--;
1440             }       
1441         }
1442 #endif
1443
1444     }
1445 #endif
1446
1447 dealloc:
1448     /* all other cases just dealloc */
1449     if (op ) {
1450         op->aop = NULL;
1451         if (IS_SYMOP(op)) {
1452             OP_SYMBOL(op)->aop = NULL;    
1453             /* if the symbol has a spill */
1454             if (SPIL_LOC(op))
1455                 SPIL_LOC(op)->aop = NULL;
1456         }
1457     }
1458 }
1459
1460 /*-----------------------------------------------------------------*/
1461 /* pic16_aopGet - for fetching value of the aop                          */
1462 /*-----------------------------------------------------------------*/
1463 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1464 {
1465     char *s = buffer ;
1466     char *rs;
1467
1468     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1469
1470     /* offset is greater than size then zero */
1471     if (offset > (aop->size - 1) &&
1472         aop->type != AOP_LIT)
1473         return zero;
1474
1475     /* depending on type */
1476     switch (aop->type) {
1477
1478     case AOP_FSR0:
1479     case AOP_FSR2:
1480       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1481       rs = Safe_calloc(1, strlen(s)+1);
1482       strcpy(rs, s);
1483       return (rs);
1484       
1485 #if 0
1486       /* if we need to increment it */
1487       while (offset > aop->coff)
1488         {
1489           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1490           aop->coff++;
1491         }
1492
1493       while (offset < aop->coff)
1494         {
1495           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1496           aop->coff--;
1497         }
1498       aop->coff = offset;
1499       if (aop->paged)
1500         {
1501           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1502           return (dname ? "acc" : "a");
1503         }
1504       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1505       rs = Safe_calloc (1, strlen (s) + 1);
1506       strcpy (rs, s);
1507       return rs;
1508 #endif
1509
1510         
1511     case AOP_IMMD:
1512         if (bit16) 
1513             sprintf (s,"%s",aop->aopu.aop_immd);
1514         else
1515             if (offset) 
1516                 sprintf(s,"(%s >> %d)",
1517                         aop->aopu.aop_immd,
1518                         offset*8);
1519             else
1520                 sprintf(s,"%s",
1521                         aop->aopu.aop_immd);
1522         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1523         rs = Safe_calloc(1,strlen(s)+1);
1524         strcpy(rs,s);   
1525         return rs;
1526         
1527     case AOP_DIR:
1528       if (offset) {
1529         sprintf(s,"(%s + %d)",
1530                 aop->aopu.aop_dir,
1531                 offset);
1532         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1533       } else
1534             sprintf(s,"%s",aop->aopu.aop_dir);
1535         rs = Safe_calloc(1,strlen(s)+1);
1536         strcpy(rs,s);   
1537         return rs;
1538         
1539     case AOP_REG:
1540       //if (dname) 
1541       //    return aop->aopu.aop_reg[offset]->dname;
1542       //else
1543             return aop->aopu.aop_reg[offset]->name;
1544         
1545     case AOP_CRY:
1546       //pic16_emitcode(";","%d",__LINE__);
1547       return aop->aopu.aop_dir;
1548         
1549     case AOP_ACC:
1550         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1551 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1552 //        assert( 0 );
1553 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1554         rs = Safe_strdup("WREG");
1555         return (rs);
1556
1557     case AOP_LIT:
1558         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1559         rs = Safe_calloc(1,strlen(s)+1);
1560         strcpy(rs,s);   
1561         return rs;
1562         
1563     case AOP_STR:
1564         aop->coff = offset ;
1565
1566 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1567 //          dname)
1568 //          return "acc";
1569         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1570           aop->type = AOP_ACC;
1571           return Safe_strdup("WREG");
1572         }
1573         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1574         
1575         return aop->aopu.aop_str[offset];
1576         
1577     case AOP_PCODE:
1578       {
1579         pCodeOp *pcop = aop->aopu.pcop;
1580         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1581         if(pcop->name) {
1582           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1583           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1584           if (offset) {
1585             sprintf(s,"(%s + %d)", pcop->name, offset);
1586           } else {
1587             sprintf(s,"%s", pcop->name);
1588           }
1589         } else
1590           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1591
1592       }
1593       rs = Safe_calloc(1,strlen(s)+1);
1594       strcpy(rs,s);   
1595       return rs;
1596
1597 #if 0
1598     case AOP_PAGED:
1599       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1600       if (offset) {
1601         sprintf(s,"(%s + %d)",
1602                 aop->aopu.aop_dir,
1603                 offset);
1604       } else
1605             sprintf(s,"%s",aop->aopu.aop_dir);
1606       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1607       rs = Safe_calloc(1,strlen(s)+1);
1608       strcpy(rs,s);   
1609       return rs;
1610 #endif
1611
1612     case AOP_STA:
1613         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1614         return (rs);
1615         
1616     case AOP_STK:
1617 //        pCodeOp *pcop = aop->aop
1618         break;
1619
1620     }
1621
1622     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1623     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1624            "aopget got unsupported aop->type");
1625     exit(0);
1626 }
1627
1628
1629
1630 /* lock has the following meaning: When allocating temporary registers
1631  * for stack variables storage, the value of the temporary register is
1632  * saved on stack. Its value is restored at the end. This procedure is
1633  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1634  * a possibility that before a call to pic16_aopOp, a temporary register
1635  * is allocated for a while and it is freed after some time, this will
1636  * mess the stack and values will not be restored properly. So use lock=1
1637  * to allocate temporary registers used internally by the programmer, and
1638  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1639  * to inform the compiler developer about a possible bug. This is an internal
1640  * feature for developing the compiler -- VR */
1641  
1642 int _TempReg_lock = 0;
1643 /*-----------------------------------------------------------------*/
1644 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1645 /*-----------------------------------------------------------------*/
1646 pCodeOp *pic16_popGetTempReg(int lock)
1647 {
1648   pCodeOp *pcop;
1649   symbol *cfunc;
1650
1651 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1652     if(_TempReg_lock) {
1653 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1654     }
1655     
1656     _TempReg_lock += lock;
1657     
1658     cfunc = currFunc;
1659     currFunc = NULL;
1660
1661     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1662     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1663       PCOR(pcop)->r->wasUsed=1;
1664       PCOR(pcop)->r->isFree=0;
1665
1666       /* push value on stack */
1667       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1668     }
1669
1670     currFunc = cfunc;
1671
1672   return pcop;
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1677 /*                           is not part of f, but don't save if   */
1678 /*                           inside v                              */
1679 /*-----------------------------------------------------------------*/
1680 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1681 {
1682   pCodeOp *pcop=NULL;
1683   symbol *cfunc;
1684   int i;
1685
1686 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1687
1688     if(_TempReg_lock) {
1689 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1690     }
1691
1692     _TempReg_lock += lock;
1693
1694     cfunc = currFunc;
1695     currFunc = NULL;
1696
1697     i = bitVectFirstBit(f);
1698     while(i < 128) {
1699
1700       /* bypass registers that are used by function */
1701       if(!bitVectBitValue(f, i)) {
1702       
1703         /* bypass registers that are already allocated for stack access */
1704         if(!bitVectBitValue(v, i))  {
1705         
1706 //          debugf("getting register rIdx = %d\n", i);
1707           /* ok, get the operand */
1708           pcop = pic16_newpCodeOpReg( i );
1709     
1710           /* should never by NULL */
1711           assert( pcop != NULL );
1712
1713           
1714           /* sanity check */
1715           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1716             int found=0;
1717             
1718               PCOR(pcop)->r->wasUsed=1;
1719               PCOR(pcop)->r->isFree=0;
1720
1721
1722               {
1723                 regs *sr;
1724               
1725                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1726
1727                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1728                       /* already used in previous steps, break */
1729                       found=1;          
1730                       break;
1731                     }
1732                   }
1733               }
1734
1735               /* caller takes care of the following */
1736 //              bitVectSetBit(v, i);
1737
1738               if(!found) {
1739                 /* push value on stack */
1740                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1742               }
1743           
1744             break;
1745           }
1746         }
1747       }
1748       i++;
1749     }
1750
1751     currFunc = cfunc;
1752
1753   return pcop;
1754 }
1755
1756
1757 /*-----------------------------------------------------------------*/
1758 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1759 /*-----------------------------------------------------------------*/
1760 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1761 {
1762   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1763
1764   _TempReg_lock -= lock;
1765
1766   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1767     PCOR(pcop)->r->isFree = 1;
1768
1769     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1770   }
1771 }
1772 /*-----------------------------------------------------------------*/
1773 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1774 /*-----------------------------------------------------------------*/
1775 pCodeOp *pic16_popGetLabel(unsigned int key)
1776 {
1777
1778   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1779
1780   if(key>max_key)
1781     max_key = key;
1782
1783   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* pic16_popCopyReg - copy a pcode operator                              */
1788 /*-----------------------------------------------------------------*/
1789 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1790 {
1791   pCodeOpReg *pcor;
1792
1793   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1794   pcor->pcop.type = pc->pcop.type;
1795   if(pc->pcop.name) {
1796     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1797       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1798   } else
1799     pcor->pcop.name = NULL;
1800
1801   pcor->r = pc->r;
1802   pcor->rIdx = pc->rIdx;
1803   pcor->r->wasUsed=1;
1804   pcor->instance = pc->instance;
1805
1806 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1807
1808   return PCOP(pcor);
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1813 /*-----------------------------------------------------------------*/
1814 pCodeOp *pic16_popGetLit(int lit)
1815 {
1816   return pic16_newpCodeOpLit(lit);
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1821 /*-----------------------------------------------------------------*/
1822 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1823 {
1824   return pic16_newpCodeOpLit2(lit, arg2);
1825 }
1826
1827
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1832 {
1833   return pic16_newpCodeOpImmd(name, offset,index, 0);
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGet - asm operator to pcode operator conversion              */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetWithString(char *str)
1841 {
1842   pCodeOp *pcop;
1843
1844
1845   if(!str) {
1846     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1847     exit (1);
1848   }
1849
1850   pcop = pic16_newpCodeOp(str,PO_STR);
1851
1852   return pcop;
1853 }
1854
1855 /*-----------------------------------------------------------------*/
1856 /* pic16_popRegFromString -                                        */
1857 /*-----------------------------------------------------------------*/
1858 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1859 {
1860
1861   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862   pcop->type = PO_DIR;
1863
1864   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1865   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1866
1867   if(!str)
1868     str = "BAD_STRING";
1869
1870   pcop->name = Safe_calloc(1,strlen(str)+1);
1871   strcpy(pcop->name,str);
1872
1873   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1874
1875   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1876
1877   /* make sure that register doesn't exist,
1878    * and operand isn't NULL
1879    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1880   if((PCOR(pcop)->r == NULL) 
1881     && (op)
1882     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1883 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1884 //              __FUNCTION__, __LINE__, str, size, offset);
1885
1886     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1887     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1888
1889   }
1890   PCOR(pcop)->instance = offset;
1891
1892   return pcop;
1893 }
1894
1895 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1896 {
1897   pCodeOp *pcop;
1898
1899 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1900
1901         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1902         PCOR(pcop)->rIdx = rIdx;
1903         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1904
1905         PCOR(pcop)->r->isFree = 0;
1906         PCOR(pcop)->r->wasUsed = 1;
1907
1908         pcop->type = PCOR(pcop)->r->pc_type;
1909
1910   return pcop;
1911 }
1912
1913 /*---------------------------------------------------------------------------------*/
1914 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1915 /*                 VR 030601                                                       */
1916 /*---------------------------------------------------------------------------------*/
1917 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1918 {
1919   pCodeOpReg2 *pcop2;
1920   pCodeOp *temp;
1921   
1922         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1923
1924         /* comment the following check, so errors to throw up */
1925 //      if(!pcop2)return NULL;
1926
1927         temp = pic16_popGet(aop_dst, offset);
1928         pcop2->pcop2 = temp;
1929         
1930   return PCOP(pcop2);
1931 }
1932
1933
1934
1935 /*--------------------------------------------------------------------------------.-*/
1936 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1937 /*                  VR 030601 , adapted by Hans Dorn                                */
1938 /*--------------------------------------------------------------------------------.-*/
1939 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1940 {
1941   pCodeOpReg2 *pcop2;
1942  
1943         pcop2 = (pCodeOpReg2 *)src;
1944         pcop2->pcop2 = dst;
1945         
1946         return PCOP(pcop2);
1947 }
1948
1949
1950
1951 /*---------------------------------------------------------------------------------*/
1952 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1953 /*                     movff instruction                                           */
1954 /*---------------------------------------------------------------------------------*/
1955 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1956 {
1957   pCodeOpReg2 *pcop2;
1958
1959         if(!noalloc) {
1960                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1961                 pcop2->pcop2 = pic16_popCopyReg(dst);
1962         } else {
1963                 /* the pCodeOp may be already allocated */
1964                 pcop2 = (pCodeOpReg2 *)(src);
1965                 pcop2->pcop2 = (pCodeOp *)(dst);
1966         }
1967
1968   return PCOP(pcop2);
1969 }
1970
1971
1972 /*-----------------------------------------------------------------*/
1973 /* pic16_popGet - asm operator to pcode operator conversion              */
1974 /*-----------------------------------------------------------------*/
1975 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1976 {
1977   //char *s = buffer ;
1978   char *rs;
1979   pCodeOp *pcop;
1980
1981     FENTRY2;
1982     /* offset is greater than
1983     size then zero */
1984
1985 //    if (offset > (aop->size - 1) &&
1986 //        aop->type != AOP_LIT)
1987 //      return NULL;  //zero;
1988
1989     /* depending on type */
1990     switch (aop->type) {
1991         
1992     case AOP_R0:
1993     case AOP_R1:
1994     case AOP_DPTR:
1995     case AOP_DPTR2:
1996         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1997         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1998         assert( 0 );
1999         return NULL;
2000
2001
2002     case AOP_FSR0:
2003     case AOP_FSR2:
2004       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2005       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2006       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2007       PCOR(pcop)->r->wasUsed = 1;
2008       PCOR(pcop)->r->isFree = 0;
2009       
2010       PCOR(pcop)->instance = offset;
2011       pcop->type = PCOR(pcop)->r->pc_type;
2012       return (pcop);
2013
2014     case AOP_IMMD:
2015       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2016       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2017
2018     case AOP_STA:
2019       /* pCodeOp is already allocated from aopForSym */
2020         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2021         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2022           
2023       return (pcop);
2024       
2025     case AOP_ACC:
2026       {
2027         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2028
2029         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2030
2031         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2032         
2033         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034         PCOR(pcop)->rIdx = rIdx;
2035         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2036         PCOR(pcop)->r->wasUsed=1;
2037         PCOR(pcop)->r->isFree=0;
2038
2039         PCOR(pcop)->instance = offset;
2040         pcop->type = PCOR(pcop)->r->pc_type;
2041 //      rs = aop->aopu.aop_reg[offset]->name;
2042 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2043         return pcop;
2044
2045
2046 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2047 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2048
2049 //      assert( 0 );
2050       }
2051         
2052     case AOP_DIR:
2053       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2054       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2055         
2056 #if 0
2057     case AOP_PAGED:
2058       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2060 #endif
2061
2062     case AOP_REG:
2063       {
2064         int rIdx;
2065         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2066         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2067
2068         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2069         
2070         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2071 //      pcop->type = PO_GPR_REGISTER;
2072         PCOR(pcop)->rIdx = rIdx;
2073         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2074         PCOR(pcop)->r->wasUsed=1;
2075         PCOR(pcop)->r->isFree=0;
2076
2077         PCOR(pcop)->instance = offset;
2078         pcop->type = PCOR(pcop)->r->pc_type;
2079         
2080         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2081         rs = aop->aopu.aop_reg[offset]->name;
2082         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2083         return pcop;
2084       }
2085
2086     case AOP_CRY:
2087         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2088
2089       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2090       PCOR(pcop)->instance = offset;
2091       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2092       //if(PCOR(pcop)->r == NULL)
2093       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2094       return pcop;
2095         
2096     case AOP_LIT:
2097         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2098       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2099
2100     case AOP_STR:
2101       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2102       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2103
2104       /*
2105       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2107       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108       pcop->type = PCOR(pcop)->r->pc_type;
2109       pcop->name = PCOR(pcop)->r->name;
2110
2111       return pcop;
2112       */
2113
2114     case AOP_PCODE:
2115       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2116                           __LINE__, 
2117                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2118       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2119       switch( aop->aopu.pcop->type ) {
2120         case PO_DIR: PCOR(pcop)->instance += offset; break;
2121         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2122         case PO_WREG:
2123             assert (offset==0);
2124             break;
2125         default:
2126           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2127           assert( 0 );  /* should never reach here */;
2128       }
2129       return pcop;
2130     }
2131
2132     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2133            "pic16_popGet got unsupported aop->type");
2134     exit(0);
2135 }
2136 /*-----------------------------------------------------------------*/
2137 /* pic16_aopPut - puts a string for a aop                                */
2138 /*-----------------------------------------------------------------*/
2139 void pic16_aopPut (asmop *aop, char *s, int offset)
2140 {
2141     char *d = buffer ;
2142     symbol *lbl ;
2143
2144     return;
2145
2146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2147
2148     if (aop->size && offset > ( aop->size - 1)) {
2149         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2150                "pic16_aopPut got offset > aop->size");
2151         exit(0);
2152     }
2153
2154     /* will assign value to value */
2155     /* depending on where it is ofcourse */
2156     switch (aop->type) {
2157     case AOP_DIR:
2158       if (offset) {
2159         sprintf(d,"(%s + %d)",
2160                 aop->aopu.aop_dir,offset);
2161         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2162
2163       } else
2164             sprintf(d,"%s",aop->aopu.aop_dir);
2165         
2166         if (strcmp(d,s)) {
2167           DEBUGpic16_emitcode(";","%d",__LINE__);
2168           if(strcmp(s,"W"))
2169             pic16_emitcode("movf","%s,w",s);
2170           pic16_emitcode("movwf","%s",d);
2171
2172           if(strcmp(s,"W")) {
2173             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2174             if(offset >= aop->size) {
2175               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2176               break;
2177             } else
2178               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2179           }
2180
2181           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2182
2183
2184         }
2185         break;
2186         
2187     case AOP_REG:
2188       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2189         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2190           /*
2191             if (*s == '@'           ||
2192                 strcmp(s,"r0") == 0 ||
2193                 strcmp(s,"r1") == 0 ||
2194                 strcmp(s,"r2") == 0 ||
2195                 strcmp(s,"r3") == 0 ||
2196                 strcmp(s,"r4") == 0 ||
2197                 strcmp(s,"r5") == 0 ||
2198                 strcmp(s,"r6") == 0 || 
2199                 strcmp(s,"r7") == 0 )
2200                 pic16_emitcode("mov","%s,%s  ; %d",
2201                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2202             else
2203           */
2204
2205           if(strcmp(s,"W")==0 )
2206             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2207
2208           pic16_emitcode("movwf","%s",
2209                    aop->aopu.aop_reg[offset]->name);
2210
2211           if(strcmp(s,zero)==0) {
2212             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2213
2214           } else if(strcmp(s,"W")==0) {
2215             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2216             pcop->type = PO_GPR_REGISTER;
2217
2218             PCOR(pcop)->rIdx = -1;
2219             PCOR(pcop)->r = NULL;
2220
2221             DEBUGpic16_emitcode(";","%d",__LINE__);
2222             pcop->name = Safe_strdup(s);
2223             pic16_emitpcode(POC_MOVFW,pcop);
2224             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2225           } else if(strcmp(s,one)==0) {
2226             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2227             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2228           } else {
2229             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230           }
2231         }
2232         break;
2233         
2234     case AOP_DPTR:
2235     case AOP_DPTR2:
2236     
2237     if (aop->type == AOP_DPTR2)
2238     {
2239         genSetDPTR(1);
2240     }
2241     
2242         if (aop->code) {
2243             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244                    "pic16_aopPut writting to code space");
2245             exit(0);
2246         }
2247         
2248         while (offset > aop->coff) {
2249             aop->coff++;
2250             pic16_emitcode ("inc","dptr");
2251         }
2252         
2253         while (offset < aop->coff) {
2254             aop->coff-- ;
2255             pic16_emitcode("lcall","__decdptr");
2256         }
2257         
2258         aop->coff = offset;
2259         
2260         /* if not in accumulater */
2261         MOVA(s);        
2262         
2263         pic16_emitcode ("movx","@dptr,a");
2264         
2265     if (aop->type == AOP_DPTR2)
2266     {
2267         genSetDPTR(0);
2268     }
2269         break;
2270         
2271     case AOP_R0:
2272     case AOP_R1:
2273         while (offset > aop->coff) {
2274             aop->coff++;
2275             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2276         }
2277         while (offset < aop->coff) {
2278             aop->coff-- ;
2279             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2280         }
2281         aop->coff = offset;
2282         
2283         if (aop->paged) {
2284             MOVA(s);           
2285             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2286             
2287         } else
2288             if (*s == '@') {
2289                 MOVA(s);
2290                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2291             } else
2292                 if (strcmp(s,"r0") == 0 ||
2293                     strcmp(s,"r1") == 0 ||
2294                     strcmp(s,"r2") == 0 ||
2295                     strcmp(s,"r3") == 0 ||
2296                     strcmp(s,"r4") == 0 ||
2297                     strcmp(s,"r5") == 0 ||
2298                     strcmp(s,"r6") == 0 || 
2299                     strcmp(s,"r7") == 0 ) {
2300                     char buffer[10];
2301                     sprintf(buffer,"a%s",s);
2302                     pic16_emitcode("mov","@%s,%s",
2303                              aop->aopu.aop_ptr->name,buffer);
2304                 } else
2305                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2306         
2307         break;
2308         
2309     case AOP_STK:
2310         if (strcmp(s,"a") == 0)
2311             pic16_emitcode("push","acc");
2312         else
2313             pic16_emitcode("push","%s",s);
2314         
2315         break;
2316         
2317     case AOP_CRY:
2318         /* if bit variable */
2319         if (!aop->aopu.aop_dir) {
2320             pic16_emitcode("clr","a");
2321             pic16_emitcode("rlc","a");
2322         } else {
2323             if (s == zero) 
2324                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2325             else
2326                 if (s == one)
2327                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2328                 else
2329                     if (!strcmp(s,"c"))
2330                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2331                     else {
2332                         lbl = newiTempLabel(NULL);
2333                         
2334                         if (strcmp(s,"a")) {
2335                             MOVA(s);
2336                         }
2337                         pic16_emitcode("clr","c");
2338                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2339                         pic16_emitcode("cpl","c");
2340                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2341                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2342                     }
2343         }
2344         break;
2345         
2346     case AOP_STR:
2347         aop->coff = offset;
2348         if (strcmp(aop->aopu.aop_str[offset],s))
2349             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2350         break;
2351         
2352     case AOP_ACC:
2353         aop->coff = offset;
2354         if (!offset && (strcmp(s,"acc") == 0))
2355             break;
2356         
2357         if (strcmp(aop->aopu.aop_str[offset],s))
2358             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2359         break;
2360
2361     default :
2362         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2363 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2364 //             "pic16_aopPut got unsupported aop->type");
2365 //      exit(0);    
2366     }    
2367
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2372 /*-----------------------------------------------------------------*/
2373 void pic16_mov2w (asmop *aop, int offset)
2374 {
2375   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2376
2377   if(is_LitAOp(aop))
2378     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2379   else
2380     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2381 }
2382
2383 static void mov2f(asmop *dst, asmop *src, int offset)
2384 {
2385   if(is_LitAOp(src)) {
2386     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2387     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2388   } else {
2389     if(pic16_sameRegsOfs(src, dst, offset))return;
2390     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2391                       pic16_popGet(dst, offset)));
2392   }
2393 }
2394
2395 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2396 {
2397   if(is_LitAOp(src)) {
2398     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2399     pic16_emitpcode(POC_MOVWF, dst);
2400   } else {
2401     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2402   }
2403 }
2404
2405 void pic16_testStackOverflow(void)
2406 {
2407 #define GSTACK_TEST_NAME        "__gstack_test"
2408
2409   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2410   
2411   {
2412     symbol *sym;
2413
2414       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2415       strcpy(sym->rname, GSTACK_TEST_NAME);
2416       checkAddSym(&externs, sym);
2417   }
2418
2419 }
2420
2421 /* push pcop into stack */
2422 void pic16_pushpCodeOp(pCodeOp *pcop)
2423 {
2424 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2425   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2426   if(pic16_options.gstack)
2427     pic16_testStackOverflow();
2428     
2429 }
2430
2431 /* pop pcop from stack */
2432 void pic16_poppCodeOp(pCodeOp *pcop)
2433 {
2434   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2435   if(pic16_options.gstack)
2436     pic16_testStackOverflow();
2437 }
2438
2439
2440 /*-----------------------------------------------------------------*/
2441 /* pushw - pushes wreg to stack                                    */
2442 /*-----------------------------------------------------------------*/
2443 void pushw(void)
2444 {
2445   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2446   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2447   if(pic16_options.gstack)
2448     pic16_testStackOverflow();
2449 }
2450
2451                 
2452 /*-----------------------------------------------------------------*/
2453 /* pushaop - pushes aop to stack                                   */
2454 /*-----------------------------------------------------------------*/
2455 void pushaop(asmop *aop, int offset)
2456 {
2457   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2458
2459   if(is_LitAOp(aop)) {
2460     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2461     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2462   } else {
2463     pic16_emitpcode(POC_MOVFF,
2464       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2465   }
2466
2467   if(pic16_options.gstack)
2468     pic16_testStackOverflow();
2469 }
2470
2471 /*-----------------------------------------------------------------*/
2472 /* popaop - pops aop from stack                                    */
2473 /*-----------------------------------------------------------------*/
2474 void popaop(asmop *aop, int offset)
2475 {
2476   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2477   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2478   if(pic16_options.gstack)
2479     pic16_testStackOverflow();
2480 }
2481
2482 void popaopidx(asmop *aop, int offset, int index)
2483 {
2484   int ofs=1;
2485
2486     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2487
2488     if(STACK_MODEL_LARGE)ofs++;
2489
2490     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2491     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2492     if(pic16_options.gstack)
2493       pic16_testStackOverflow();
2494 }
2495
2496 #if !(USE_GENERIC_SIGNED_SHIFT)
2497 /*-----------------------------------------------------------------*/
2498 /* reAdjustPreg - points a register back to where it should        */
2499 /*-----------------------------------------------------------------*/
2500 static void reAdjustPreg (asmop *aop)
2501 {
2502     int size ;
2503
2504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2505     aop->coff = 0;
2506     if ((size = aop->size) <= 1)
2507         return ;
2508     size-- ;
2509     switch (aop->type) {
2510         case AOP_R0 :
2511         case AOP_R1 :
2512             while (size--)
2513                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2514             break;          
2515         case AOP_DPTR :
2516         case AOP_DPTR2:
2517             if (aop->type == AOP_DPTR2)
2518             {
2519                 genSetDPTR(1);
2520             } 
2521             while (size--)
2522             {
2523                 pic16_emitcode("lcall","__decdptr");
2524             }
2525                 
2526             if (aop->type == AOP_DPTR2)
2527             {
2528                 genSetDPTR(0);
2529             }                
2530             break;  
2531
2532     }   
2533
2534 }
2535 #endif
2536
2537 #if 0
2538 /*-----------------------------------------------------------------*/
2539 /* opIsGptr: returns non-zero if the passed operand is             */   
2540 /* a generic pointer type.                                         */
2541 /*-----------------------------------------------------------------*/ 
2542 static int opIsGptr(operand *op)
2543 {
2544     sym_link *type = operandType(op);
2545     
2546     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2547     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2548     {
2549         return 1;
2550     }
2551     return 0;        
2552 }
2553 #endif
2554
2555 /*-----------------------------------------------------------------*/
2556 /* pic16_getDataSize - get the operand data size                         */
2557 /*-----------------------------------------------------------------*/
2558 int pic16_getDataSize(operand *op)
2559 {
2560     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2561
2562
2563     return AOP_SIZE(op);
2564
2565     // tsd- in the pic port, the genptr size is 1, so this code here
2566     // fails. ( in the 8051 port, the size was 4).
2567 #if 0
2568     int size;
2569     size = AOP_SIZE(op);
2570     if (size == GPTRSIZE)
2571     {
2572         sym_link *type = operandType(op);
2573         if (IS_GENPTR(type))
2574         {
2575             /* generic pointer; arithmetic operations
2576              * should ignore the high byte (pointer type).
2577              */
2578             size--;
2579     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2580         }
2581     }
2582     return size;
2583 #endif
2584 }
2585
2586 /*-----------------------------------------------------------------*/
2587 /* pic16_outAcc - output Acc                                             */
2588 /*-----------------------------------------------------------------*/
2589 void pic16_outAcc(operand *result)
2590 {
2591   int size,offset;
2592   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2593   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2594
2595
2596   size = pic16_getDataSize(result);
2597   if(size){
2598     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2599     size--;
2600     offset = 1;
2601     /* unsigned or positive */
2602     while(size--)
2603       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2604   }
2605
2606 }
2607
2608 /*-----------------------------------------------------------------*/
2609 /* pic16_outBitC - output a bit C                                  */
2610 /*                 Move to result the value of Carry flag -- VR    */
2611 /*-----------------------------------------------------------------*/
2612 void pic16_outBitC(operand *result)
2613 {
2614   int i;
2615
2616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2617
2618     /* if the result is bit */
2619     if (AOP_TYPE(result) == AOP_CRY) {
2620         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2621         pic16_aopPut(AOP(result),"c",0);
2622     } else {
2623
2624         i = AOP_SIZE(result);
2625         while(i--) {
2626                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2627         }
2628         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2629     }
2630 }
2631
2632 /*-----------------------------------------------------------------*/
2633 /* pic16_outBitOp - output a bit from Op                           */
2634 /*                 Move to result the value of set/clr op -- VR    */
2635 /*-----------------------------------------------------------------*/
2636 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2637 {
2638   int i;
2639
2640     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2641
2642     /* if the result is bit */
2643     if (AOP_TYPE(result) == AOP_CRY) {
2644         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2645         pic16_aopPut(AOP(result),"c",0);
2646     } else {
2647
2648         i = AOP_SIZE(result);
2649         while(i--) {
2650                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2651         }
2652         pic16_emitpcode(POC_RRCF, pcop);          
2653         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2654     }
2655 }
2656
2657 /*-----------------------------------------------------------------*/
2658 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2659 /*-----------------------------------------------------------------*/
2660 void pic16_toBoolean(operand *oper)
2661 {
2662     int size = AOP_SIZE(oper) - 1;
2663     int offset = 1;
2664
2665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2666
2667     if ( AOP_TYPE(oper) != AOP_ACC) {
2668       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2669     }
2670     while (size--) {
2671       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2672     }
2673 }
2674
2675
2676 #if !defined(GEN_Not)
2677 /*-----------------------------------------------------------------*/
2678 /* genNot - generate code for ! operation                          */
2679 /*-----------------------------------------------------------------*/
2680 static void pic16_genNot (iCode *ic)
2681 {
2682   symbol *tlbl;
2683   int size;
2684
2685   FENTRY;
2686   /* assign asmOps to operand & result */
2687   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2688   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2689
2690   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2691   /* if in bit space then a special case */
2692   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2693     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2694       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2695       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2696     } else {
2697       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2698       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2699       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2700     }
2701     goto release;
2702   }
2703
2704   size = AOP_SIZE(IC_LEFT(ic));
2705   if(size == 1) {
2706     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2707     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2708     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2709     goto release;
2710   }
2711   pic16_toBoolean(IC_LEFT(ic));
2712
2713   tlbl = newiTempLabel(NULL);
2714   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2715   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2716   pic16_outBitC(IC_RESULT(ic));
2717
2718  release:    
2719   /* release the aops */
2720   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2721   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2722 }
2723 #endif
2724
2725
2726 #if !defined(GEN_Cpl)
2727 /*-----------------------------------------------------------------*/
2728 /* genCpl - generate code for complement                           */
2729 /*-----------------------------------------------------------------*/
2730 static void pic16_genCpl (iCode *ic)
2731 {
2732   int offset = 0;
2733   int size ;
2734
2735     FENTRY;
2736     /* assign asmOps to operand & result */
2737     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2738     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2739
2740     /* if both are in bit space then 
2741     a special case */
2742     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2743         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2744
2745         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2746         pic16_emitcode("cpl","c"); 
2747         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2748         goto release; 
2749     } 
2750
2751     size = AOP_SIZE(IC_RESULT(ic));
2752     while (size--) {
2753 /*
2754         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2755         MOVA(l);       
2756         pic16_emitcode("cpl","a");
2757         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2758 */
2759         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2760               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2761         } else {
2762                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2763                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2764         }
2765         offset++;
2766
2767     }
2768
2769
2770 release:
2771     /* release the aops */
2772     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2773     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2774 }
2775 #endif
2776
2777 /*-----------------------------------------------------------------*/
2778 /* genUminusFloat - unary minus for floating points                */
2779 /*-----------------------------------------------------------------*/
2780 static void genUminusFloat(operand *op,operand *result)
2781 {
2782   int size ,offset =0 ;
2783   
2784     FENTRY;
2785     /* for this we just need to flip the 
2786     first it then copy the rest in place */
2787     size = AOP_SIZE(op);
2788
2789     while(size--) {
2790       mov2f(AOP(result), AOP(op), offset);
2791       offset++;
2792     }
2793     
2794     /* toggle the MSB's highest bit */
2795     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2796 }
2797
2798 /*-----------------------------------------------------------------*/
2799 /* genUminus - unary minus code generation                         */
2800 /*-----------------------------------------------------------------*/
2801 static void genUminus (iCode *ic)
2802 {
2803   int size, i;
2804   sym_link *optype, *rtype;
2805   symbol *label;
2806   int needLabel=0;
2807
2808     FENTRY;     
2809     
2810     /* assign asmops */
2811     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2812     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2813
2814     /* if both in bit space then special case */
2815     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2816       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2817         
2818         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2819         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2820         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2821         goto release; 
2822     } 
2823
2824     optype = operandType(IC_LEFT(ic));
2825     rtype = operandType(IC_RESULT(ic));
2826
2827     /* if float then do float stuff */
2828     if (IS_FLOAT(optype)) {
2829       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2830       goto release;
2831     }
2832
2833     /* otherwise subtract from zero by taking the 2's complement */
2834     size = AOP_SIZE(IC_LEFT(ic));
2835     label = newiTempLabel ( NULL );
2836     
2837     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2838       for (i=size-1; i > 0; i--) {
2839         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2840       } // for
2841       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2842       for (i=1; i < size; i++) {
2843         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2844         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845       } // for
2846     } else {
2847       for (i=size-1; i >= 0; i--) {
2848         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2849         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2850       } // for
2851       if (size > 1) {
2852         for (i=0; i < size-2; i++) {
2853           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2854           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2855         } // for
2856         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2857       } // if
2858       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2859     }
2860     if (needLabel)
2861       pic16_emitpLabel (label->key);
2862
2863 release:
2864     /* release the aops */
2865     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2866     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2867 }
2868
2869 #if 0
2870 /*-----------------------------------------------------------------*/
2871 /* saveRegisters - will look for a call and save the registers     */
2872 /*-----------------------------------------------------------------*/
2873 static void saveRegisters(iCode *lic) 
2874 {
2875     int i;
2876     iCode *ic;
2877     bitVect *rsave;
2878     sym_link *dtype;
2879
2880     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2881     /* look for call */
2882     for (ic = lic ; ic ; ic = ic->next) 
2883         if (ic->op == CALL || ic->op == PCALL)
2884             break;
2885
2886     if (!ic) {
2887         fprintf(stderr,"found parameter push with no function call\n");
2888         return ;
2889     }
2890
2891     /* if the registers have been saved already then
2892     do nothing */
2893     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2894         return ;
2895
2896     /* find the registers in use at this time 
2897     and push them away to safety */
2898     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2899                           ic->rUsed);
2900
2901     ic->regsSaved = 1;
2902     if (options.useXstack) {
2903         if (bitVectBitValue(rsave,R0_IDX))
2904             pic16_emitcode("mov","b,r0");
2905         pic16_emitcode("mov","r0,%s",spname);
2906         for (i = 0 ; i < pic16_nRegs ; i++) {
2907             if (bitVectBitValue(rsave,i)) {
2908                 if (i == R0_IDX)
2909                     pic16_emitcode("mov","a,b");
2910                 else
2911                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2912                 pic16_emitcode("movx","@r0,a");
2913                 pic16_emitcode("inc","r0");
2914             }
2915         }
2916         pic16_emitcode("mov","%s,r0",spname);
2917         if (bitVectBitValue(rsave,R0_IDX))
2918             pic16_emitcode("mov","r0,b");           
2919     }// else
2920     //for (i = 0 ; i < pic16_nRegs ; i++) {
2921     //    if (bitVectBitValue(rsave,i))
2922     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2923     //}
2924
2925     dtype = operandType(IC_LEFT(ic));
2926     if (currFunc && dtype && 
2927         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2928         IFFUNC_ISISR(currFunc->type) &&
2929         !ic->bankSaved) 
2930
2931         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2932
2933 }
2934 /*-----------------------------------------------------------------*/
2935 /* unsaveRegisters - pop the pushed registers                      */
2936 /*-----------------------------------------------------------------*/
2937 static void unsaveRegisters (iCode *ic)
2938 {
2939     int i;
2940     bitVect *rsave;
2941
2942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2943     /* find the registers in use at this time 
2944     and push them away to safety */
2945     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2946                           ic->rUsed);
2947     
2948     if (options.useXstack) {
2949         pic16_emitcode("mov","r0,%s",spname);   
2950         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2951             if (bitVectBitValue(rsave,i)) {
2952                 pic16_emitcode("dec","r0");
2953                 pic16_emitcode("movx","a,@r0");
2954                 if (i == R0_IDX)
2955                     pic16_emitcode("mov","b,a");
2956                 else
2957                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2958             }       
2959
2960         }
2961         pic16_emitcode("mov","%s,r0",spname);
2962         if (bitVectBitValue(rsave,R0_IDX))
2963             pic16_emitcode("mov","r0,b");
2964     } //else
2965     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2966     //    if (bitVectBitValue(rsave,i))
2967     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2968     //}
2969
2970 }  
2971 #endif
2972
2973 #if 0  // patch 14
2974 /*-----------------------------------------------------------------*/
2975 /* pushSide -                                                      */
2976 /*-----------------------------------------------------------------*/
2977 static void pushSide(operand * oper, int size)
2978 {
2979         int offset = 0;
2980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2981         while (size--) {
2982                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2983                 if (AOP_TYPE(oper) != AOP_REG &&
2984                     AOP_TYPE(oper) != AOP_DIR &&
2985                     strcmp(l,"a") ) {
2986                         pic16_emitcode("mov","a,%s",l);
2987                         pic16_emitcode("push","acc");
2988                 } else
2989                         pic16_emitcode("push","%s",l);
2990         }
2991 }
2992 #endif // patch 14
2993
2994 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2995 {
2996   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2997     pic16_emitpcode(POC_MOVFW, src);
2998     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2999   } else {
3000     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3001         src, pic16_popGet(AOP(op), offset)));
3002   }
3003 }
3004
3005
3006 /*-----------------------------------------------------------------*/
3007 /* assignResultValue - assign results to oper, rescall==1 is       */
3008 /*                     called from genCall() or genPcall()         */
3009 /*-----------------------------------------------------------------*/
3010 static void assignResultValue(operand * oper, int rescall)
3011 {
3012   int size = AOP_SIZE(oper);
3013   int offset=0;
3014   
3015     FENTRY2;
3016 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3017     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3018
3019     if(rescall) {
3020       /* assign result from a call/pcall function() */
3021                 
3022       /* function results are stored in a special order,
3023        * see top of file with Function return policy, or manual */
3024
3025       if(size <= 4) {
3026         /* 8-bits, result in WREG */
3027         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3028                         
3029         if(size>1) {
3030           /* 16-bits, result in PRODL:WREG */
3031           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3032         }
3033                         
3034         if(size>2) {
3035           /* 24-bits, result in PRODH:PRODL:WREG */
3036           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3037         }
3038                         
3039         if(size>3) {
3040           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3041           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3042         }
3043       
3044       } else {
3045         /* >32-bits, result on stack, and FSR0 points to beginning.
3046          * Fix stack when done */
3047         /* FIXME FIXME */
3048 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3049         while (size--) {
3050 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3051 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3052                 
3053           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3054           GpsuedoStkPtr++;
3055         }
3056                         
3057         /* fix stack */
3058         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3059         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3060         if(STACK_MODEL_LARGE) {
3061           emitSKPNC;
3062           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3063         }
3064       }                 
3065     } else {
3066       int areg = 0;             /* matching argument register */
3067       
3068 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3069       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3070
3071
3072       /* its called from genReceive (probably) -- VR */
3073       /* I hope this code will not be called from somewhere else in the future! 
3074        * We manually set the pseudo stack pointer in genReceive. - dw
3075        */
3076       if(!GpsuedoStkPtr && _G.useWreg) {
3077 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3078
3079         /* The last byte in the assignment is in W */
3080         if(areg <= GpsuedoStkPtr) {
3081           size--;
3082           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3083           offset++;
3084 //          debugf("receive from WREG\n", 0);
3085         }
3086         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3087       }
3088 //      GpsuedoStkPtr++;
3089       _G.stack_lat = AOP_SIZE(oper)-1;
3090
3091       while (size) {
3092         size--;
3093         GpsuedoStkPtr++;
3094         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3095 //        debugf("receive from STACK\n", 0);
3096         offset++;
3097       }
3098     }
3099 }
3100
3101
3102 /*-----------------------------------------------------------------*/
3103 /* genIpush - generate code for pushing this gets a little complex */
3104 /*-----------------------------------------------------------------*/
3105 static void genIpush (iCode *ic)
3106 {
3107 //  int size, offset=0;
3108
3109   FENTRY;
3110   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3111
3112   if(ic->parmPush) {
3113     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3114
3115     /* send to stack as normal */
3116     addSet(&_G.sendSet,ic);
3117 //    addSetHead(&_G.sendSet,ic);
3118     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3119   }
3120
3121         
3122 #if 0
3123     int size, offset = 0 ;
3124     char *l;
3125
3126
3127     /* if this is not a parm push : ie. it is spill push 
3128     and spill push is always done on the local stack */
3129     if (!ic->parmPush) {
3130
3131         /* and the item is spilt then do nothing */
3132         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3133             return ;
3134
3135         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3136         size = AOP_SIZE(IC_LEFT(ic));
3137         /* push it on the stack */
3138         while(size--) {
3139             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3140             if (*l == '#') {
3141                 MOVA(l);
3142                 l = "acc";
3143             }
3144             pic16_emitcode("push","%s",l);
3145         }
3146         return ;        
3147     }
3148
3149     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3150 #endif
3151 }
3152
3153 /*-----------------------------------------------------------------*/
3154 /* genIpop - recover the registers: can happen only for spilling   */
3155 /*-----------------------------------------------------------------*/
3156 static void genIpop (iCode *ic)
3157 {
3158   FENTRY;
3159   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3160 #if 0
3161     int size,offset ;
3162
3163
3164     /* if the temp was not pushed then */
3165     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3166         return ;
3167
3168     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3169     size = AOP_SIZE(IC_LEFT(ic));
3170     offset = (size-1);
3171     while (size--) 
3172         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3173                                    FALSE,TRUE));
3174
3175     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3176 #endif
3177 }
3178
3179 #if 0
3180 /*-----------------------------------------------------------------*/
3181 /* unsaverbank - restores the resgister bank from stack            */
3182 /*-----------------------------------------------------------------*/
3183 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3184 {
3185   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3186 #if 0
3187     int i;
3188     asmop *aop ;
3189     regs *r = NULL;
3190
3191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3192     if (popPsw) {
3193         if (options.useXstack) {
3194             aop = newAsmop(0);
3195             r = getFreePtr(ic,&aop,FALSE);
3196             
3197             
3198             pic16_emitcode("mov","%s,_spx",r->name);
3199             pic16_emitcode("movx","a,@%s",r->name);
3200             pic16_emitcode("mov","psw,a");
3201             pic16_emitcode("dec","%s",r->name);
3202             
3203         }else
3204             pic16_emitcode ("pop","psw");
3205     }
3206
3207     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3208         if (options.useXstack) {       
3209             pic16_emitcode("movx","a,@%s",r->name);
3210             //pic16_emitcode("mov","(%s+%d),a",
3211             //       regspic16[i].base,8*bank+regspic16[i].offset);
3212             pic16_emitcode("dec","%s",r->name);
3213
3214         } else 
3215           pic16_emitcode("pop",""); //"(%s+%d)",
3216         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3217     }
3218
3219     if (options.useXstack) {
3220
3221         pic16_emitcode("mov","_spx,%s",r->name);
3222         pic16_freeAsmop(NULL,aop,ic,TRUE);
3223
3224     }
3225 #endif 
3226 }
3227
3228 /*-----------------------------------------------------------------*/
3229 /* saverbank - saves an entire register bank on the stack          */
3230 /*-----------------------------------------------------------------*/
3231 static void saverbank (int bank, iCode *ic, bool pushPsw)
3232 {
3233   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3234 #if 0
3235     int i;
3236     asmop *aop ;
3237     regs *r = NULL;
3238
3239     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3240     if (options.useXstack) {
3241
3242         aop = newAsmop(0);
3243         r = getFreePtr(ic,&aop,FALSE);  
3244         pic16_emitcode("mov","%s,_spx",r->name);
3245
3246     }
3247
3248     for (i = 0 ; i < pic16_nRegs ;i++) {
3249         if (options.useXstack) {
3250             pic16_emitcode("inc","%s",r->name);
3251             //pic16_emitcode("mov","a,(%s+%d)",
3252             //         regspic16[i].base,8*bank+regspic16[i].offset);
3253             pic16_emitcode("movx","@%s,a",r->name);           
3254         } else 
3255           pic16_emitcode("push","");// "(%s+%d)",
3256                      //regspic16[i].base,8*bank+regspic16[i].offset);
3257     }
3258     
3259     if (pushPsw) {
3260         if (options.useXstack) {
3261             pic16_emitcode("mov","a,psw");
3262             pic16_emitcode("movx","@%s,a",r->name);     
3263             pic16_emitcode("inc","%s",r->name);
3264             pic16_emitcode("mov","_spx,%s",r->name);       
3265             pic16_freeAsmop (NULL,aop,ic,TRUE);
3266             
3267         } else
3268             pic16_emitcode("push","psw");
3269         
3270         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3271     }
3272     ic->bankSaved = 1;
3273 #endif
3274 }
3275 #endif  /* 0 */
3276
3277
3278 static int wparamCmp(void *p1, void *p2)
3279 {
3280   return (!strcmp((char *)p1, (char *)p2));
3281 }
3282
3283 int inWparamList(char *s)
3284 {
3285   return isinSetWith(wparamList, s, wparamCmp);
3286
3287
3288
3289 /*-----------------------------------------------------------------*/
3290 /* genCall - generates a call statement                            */
3291 /*-----------------------------------------------------------------*/
3292 static void genCall (iCode *ic)
3293 {
3294   sym_link *ftype;   
3295   int stackParms=0;
3296   int use_wreg=0;
3297   int inwparam=0;
3298   char *fname;
3299   
3300     FENTRY;
3301
3302     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3303     /* if caller saves & we have not saved then */
3304 //    if (!ic->regsSaved)
3305 //      saveRegisters(ic);
3306
3307         /* initialise stackParms for IPUSH pushes */
3308 //      stackParms = psuedoStkPtr;
3309 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3310     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3311     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3312
3313 #if 0
3314     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3315 #endif
3316
3317     /* if send set is not empty the assign */
3318     if (_G.sendSet) {
3319       iCode *sic;
3320       int psuedoStkPtr=-1; 
3321       int firstTimeThruLoop = 1;
3322
3323
3324         /* reverse sendSet if function is not reentrant */
3325         if(!IFFUNC_ISREENT(ftype))
3326           _G.sendSet = reverseSet(_G.sendSet);
3327
3328         /* First figure how many parameters are getting passed */
3329         stackParms = 0;
3330         use_wreg = 0;
3331         
3332         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3333           int size;
3334 //          int offset = 0;
3335
3336             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3337             size = AOP_SIZE(IC_LEFT(sic));
3338
3339             stackParms += size;
3340
3341             /* pass the last byte through WREG */
3342             if(inwparam) {
3343
3344               while (size--) {
3345                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3348
3349                 if(!firstTimeThruLoop) {
3350                   /* If this is not the first time we've been through the loop
3351                    * then we need to save the parameter in a temporary
3352                    * register. The last byte of the last parameter is
3353                    * passed in W. */
3354
3355                   pushw();
3356 //                  --psuedoStkPtr;             // sanity check
3357                   use_wreg = 1;
3358                 }
3359                 
3360                 firstTimeThruLoop=0;
3361
3362                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3363
3364 //                offset++;
3365               }
3366             } else {
3367               /* all arguments are passed via stack */
3368               use_wreg = 0;
3369
3370               while (size--) {
3371                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3372                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3373                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3374
3375 //                pushaop(AOP(IC_LEFT(sic)), size);
3376                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3377
3378                 if(!_G.resDirect)
3379                   pushw();
3380               }
3381             }
3382
3383             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3384           }
3385
3386           if(inwparam) {
3387             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3388               pushw();  /* save last parameter to stack if functions has varargs */
3389               use_wreg = 0;
3390             } else
3391               use_wreg = 1;
3392           } else use_wreg = 0;
3393
3394           _G.stackRegSet = _G.sendSet;
3395           _G.sendSet = NULL;
3396     }
3397
3398     /* make the call */
3399     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3400
3401     GpsuedoStkPtr=0;
3402     
3403     /* if we need to assign a result value */
3404     if ((IS_ITEMP(IC_RESULT(ic))
3405           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3406               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3407         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3408
3409       _G.accInUse++;
3410       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3411       _G.accInUse--;
3412
3413       assignResultValue(IC_RESULT(ic), 1);
3414
3415       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3416                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3417                 
3418       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3419     }
3420
3421     if(!stackParms && ic->parmBytes) {
3422       stackParms = ic->parmBytes;
3423     }
3424       
3425     stackParms -= use_wreg;
3426     
3427     if(stackParms>0) {
3428       if(stackParms == 1) {
3429         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3430       } else {
3431         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3432         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3433       }
3434       if(STACK_MODEL_LARGE) {
3435         emitSKPNC;
3436         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3437       }
3438     }
3439
3440 #if 0
3441     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3442 #endif
3443
3444     /* adjust the stack for parameters if required */
3445 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3446
3447 #if 0
3448       /* if register bank was saved then pop them */
3449       if (ic->bankSaved)
3450         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3451
3452       /* if we hade saved some registers then unsave them */
3453       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3454         unsaveRegisters (ic);
3455 #endif
3456 }
3457
3458
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genPcall - generates a call by pointer statement                */
3462 /*            new version, created from genCall - HJD              */
3463 /*-----------------------------------------------------------------*/
3464 static void genPcall (iCode *ic)
3465 {
3466   sym_link *ftype, *fntype;
3467   int stackParms=0;
3468   symbol *retlbl = newiTempLabel(NULL);
3469   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3470   
3471     FENTRY;
3472
3473     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3474     fntype = operandType( IC_LEFT(ic) )->next;
3475
3476     /* if send set is not empty the assign */
3477     if (_G.sendSet) {
3478       iCode *sic;
3479       int psuedoStkPtr=-1; 
3480
3481       /* reverse sendSet if function is not reentrant */
3482       if(!IFFUNC_ISREENT(fntype))
3483         _G.sendSet = reverseSet(_G.sendSet);
3484
3485       stackParms = 0;
3486       
3487       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3488         int size;
3489
3490           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3491           size = AOP_SIZE(IC_LEFT(sic));
3492           stackParms += size;
3493
3494           /* all parameters are passed via stack, since WREG is clobbered
3495            * by the calling sequence */
3496           while (size--) {
3497             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3499             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3500
3501             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3502             pushw();
3503           }
3504
3505           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3506       }
3507
3508       _G.stackRegSet = _G.sendSet;
3509       _G.sendSet = NULL;
3510     }
3511
3512     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3513
3514     // push return address
3515     // push $ on return stack, then replace with retlbl
3516
3517     /* Thanks to Thorsten Klose for pointing out that the following
3518      * snippet should be interrupt safe */
3519     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3520     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3521
3522     pic16_emitpcodeNULLop(POC_PUSH);
3523
3524     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3525     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3526     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3527     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3528     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3530
3531
3532     /* restore interrupt control register */
3533     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3534     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3535
3536     /* make the call by writing the pointer into pc */
3537     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3538     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3539
3540     // note: MOVFF to PCL not allowed
3541     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3542     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3543
3544
3545     /* return address is here: (X) */
3546     pic16_emitpLabelFORCE(retlbl->key);
3547
3548     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3549
3550     GpsuedoStkPtr=0;
3551     /* if we need assign a result value */
3552     if ((IS_ITEMP(IC_RESULT(ic))
3553           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3554               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3555         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3556
3557       _G.accInUse++;
3558       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3559       _G.accInUse--;
3560
3561       assignResultValue(IC_RESULT(ic), 1);
3562
3563       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3564               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3565                 
3566       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3567     }
3568
3569 //    stackParms -= use_wreg;
3570     
3571     if(stackParms>0) {
3572       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3573       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3574       if(STACK_MODEL_LARGE) {
3575         emitSKPNC;
3576         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3577       }
3578     }
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* resultRemat - result  is rematerializable                       */
3583 /*-----------------------------------------------------------------*/
3584 static int resultRemat (iCode *ic)
3585 {
3586   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3587   if (SKIP_IC(ic) || ic->op == IFX)
3588     return 0;
3589
3590   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3591     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3592     if (sym->remat && !POINTER_SET(ic)) 
3593       return 1;
3594   }
3595
3596   return 0;
3597 }
3598
3599 #if defined(__BORLANDC__) || defined(_MSC_VER)
3600 #define STRCASECMP stricmp
3601 #else
3602 #define STRCASECMP strcasecmp
3603 #endif
3604
3605 #if 0
3606 /*-----------------------------------------------------------------*/
3607 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3608 /*-----------------------------------------------------------------*/
3609 static bool inExcludeList(char *s)
3610 {
3611   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3612     int i =0;
3613     
3614     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3615     if (options.excludeRegs[i] &&
3616     STRCASECMP(options.excludeRegs[i],"none") == 0)
3617         return FALSE ;
3618
3619     for ( i = 0 ; options.excludeRegs[i]; i++) {
3620         if (options.excludeRegs[i] &&
3621         STRCASECMP(s,options.excludeRegs[i]) == 0)
3622             return TRUE;
3623     }
3624     return FALSE ;
3625 }
3626 #endif
3627
3628 /*-----------------------------------------------------------------*/
3629 /* genFunction - generated code for function entry                 */
3630 /*-----------------------------------------------------------------*/
3631 static void genFunction (iCode *ic)
3632 {
3633   symbol *sym;
3634   sym_link *ftype;
3635   
3636     FENTRY;
3637     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3638
3639     pic16_labelOffset += (max_key+4);
3640     max_key=0;
3641     GpsuedoStkPtr=0;
3642     _G.nRegsSaved = 0;
3643         
3644     ftype = operandType(IC_LEFT(ic));
3645     sym = OP_SYMBOL(IC_LEFT(ic));
3646
3647     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3648       /* create an absolute section at the interrupt vector:
3649        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3650       symbol *asym;
3651       char asymname[128];
3652       pBlock *apb;
3653
3654 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3655
3656         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3657           sprintf(asymname, "ivec_%s", sym->name);
3658         else
3659           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3660         asym = newSymbol(asymname, 0);
3661
3662         /* FIXME: when an interrupt is declared as naked, do not emit the special
3663          * wrapper segment at vector address. The user should take care for this
3664          * instead. -- VR */
3665         
3666         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3667         pic16_addpBlock( apb );
3668
3669         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3670         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3671         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3672                 
3673         /* mark the end of this tiny function */
3674         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3675
3676         {
3677           absSym *abSym;
3678
3679             abSym = Safe_calloc(1, sizeof(absSym));
3680             strcpy(abSym->name, asymname);
3681
3682             switch( FUNC_INTNO(sym->type) ) {
3683               case 0: abSym->address = 0x000000; break;
3684               case 1: abSym->address = 0x000008; break;
3685               case 2: abSym->address = 0x000018; break;
3686               
3687               default:
3688                 fprintf(stderr, "no interrupt number is given\n");
3689                 abSym->address = -1; break;
3690             }
3691
3692             /* relocate interrupt vectors if needed */
3693             if(abSym->address != -1)
3694               abSym->address += pic16_options.ivt_loc;
3695
3696             addSet(&absSymSet, abSym);
3697         }
3698     }
3699
3700     /* create the function header */
3701     pic16_emitcode(";","-----------------------------------------");
3702     pic16_emitcode(";"," function %s",sym->name);
3703     pic16_emitcode(";","-----------------------------------------");
3704
3705     pic16_emitcode("","%s:",sym->rname);
3706     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3707
3708
3709     {
3710       absSym *ab;
3711
3712         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3713           if(!strcmp(ab->name, sym->rname)) {
3714             pic16_pBlockConvert2Absolute(pb);
3715             break;
3716           }
3717         }
3718     }
3719
3720
3721     if(IFFUNC_ISNAKED(ftype)) {
3722       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3723       return;
3724     }
3725         
3726     /* if critical function then turn interrupts off */
3727     if (IFFUNC_ISCRITICAL(ftype)) {
3728       //pic16_emitcode("clr","ea");
3729     }
3730
3731     currFunc = sym;             /* update the currFunc symbol */
3732     _G.fregsUsed = sym->regsUsed;
3733     _G.sregsAlloc = newBitVect(128);
3734     
3735
3736     /* if this is an interrupt service routine then
3737      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3738     if (IFFUNC_ISISR(sym->type)) {
3739         _G.usefastretfie = 1;   /* use shadow registers by default */
3740         
3741         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3742         if(!FUNC_ISSHADOWREGS(sym->type)) {
3743           /* do not save WREG,STATUS,BSR for high priority interrupts
3744            * because they are stored in the hardware shadow registers already */
3745           _G.usefastretfie = 0;
3746           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3747           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3748           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3749         }
3750
3751         /* these should really be optimized somehow, because not all
3752          * interrupt handlers modify them */
3753         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3754         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3755         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3756         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3757         
3758 //        pic16_pBlockConvert2ISR(pb);
3759     }
3760
3761     /* emit code to setup stack frame if user enabled,
3762      * and function is not main() */
3763     
3764 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3765     if(strcmp(sym->name, "main")) {
3766       if(0 
3767         || !options.ommitFramePtr 
3768 //        || sym->regsUsed
3769         || IFFUNC_ARGS(sym->type)
3770         || FUNC_HASSTACKPARM(sym->etype)
3771         ) {
3772         /* setup the stack frame */
3773         if(STACK_MODEL_LARGE)
3774           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3775         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3776
3777         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3778         if(STACK_MODEL_LARGE)
3779           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3780       }
3781     }
3782
3783     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3784           && sym->stack) {
3785
3786       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3787
3788       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3789       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3790       emitSKPC;
3791       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3792     }
3793           
3794     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3795       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3796         _G.useWreg = 0;
3797       else
3798         _G.useWreg = 1;
3799     } else
3800       _G.useWreg = 0;
3801
3802     /* if callee-save to be used for this function
3803      * then save the registers being used in this function */
3804 //    if (IFFUNC_CALLEESAVES(sym->type))
3805     {
3806       int i;
3807
3808         /* if any registers used */
3809         if (sym->regsUsed) {
3810           /* save the registers used */
3811           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3812           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3813           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3814             if (bitVectBitValue(sym->regsUsed,i)) {
3815               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3816               _G.nRegsSaved++;
3817
3818               if(!pic16_regWithIdx(i)->wasUsed) {
3819                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3820                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3821                 pic16_regWithIdx(i)->wasUsed = 1;
3822               }
3823             }
3824           }
3825           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3826         }
3827     }
3828         
3829     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3830 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3831 }
3832
3833 /*-----------------------------------------------------------------*/
3834 /* genEndFunction - generates epilogue for functions               */
3835 /*-----------------------------------------------------------------*/
3836 static void genEndFunction (iCode *ic)
3837 {
3838   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3839
3840     FENTRY;
3841
3842     if(IFFUNC_ISNAKED(sym->type)) {
3843       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3844       return;
3845     }
3846
3847     _G.stack_lat = 0;
3848
3849     /* add code for ISCRITICAL */
3850     if(IFFUNC_ISCRITICAL(sym->type)) {
3851       /* if critical function, turn on interrupts */
3852       
3853       /* TODO: add code here -- VR */
3854     }
3855     
3856 //    sym->regsUsed = _G.fregsUsed;
3857     
3858     /* now we need to restore the registers */
3859     /* if any registers used */
3860
3861     /* first restore registers that might be used for stack access */
3862     if(_G.sregsAllocSet) {
3863     regs *sr;
3864     
3865       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3866       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3867         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3868       }
3869     }
3870
3871     if (sym->regsUsed) {
3872       int i;
3873
3874         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3875         /* restore registers used */
3876         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3877         for ( i = sym->regsUsed->size; i >= 0; i--) {
3878           if (bitVectBitValue(sym->regsUsed,i)) {
3879             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3880             _G.nRegsSaved--;
3881           }
3882         }
3883         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3884     }
3885
3886       
3887
3888     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3889           && sym->stack) {
3890       if (sym->stack == 1) {
3891         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3892         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3893       } else {
3894         // we have to add more than one...
3895         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3896         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3897         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3898         emitSKPNC;
3899         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3900         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3901         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3902       }
3903     }
3904
3905     if(strcmp(sym->name, "main")) {
3906       if(0
3907         || !options.ommitFramePtr
3908 //        || sym->regsUsed
3909         || IFFUNC_ARGS(sym->type)
3910         || FUNC_HASSTACKPARM(sym->etype)
3911         ) {
3912         /* restore stack frame */
3913         if(STACK_MODEL_LARGE)
3914           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3915         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3916       }
3917     }
3918
3919     _G.useWreg = 0;
3920
3921     if (IFFUNC_ISISR(sym->type)) {
3922       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3923       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3924       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3925       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3926
3927       if(!FUNC_ISSHADOWREGS(sym->type)) {
3928         /* do not restore interrupt vector for WREG,STATUS,BSR
3929          * for high priority interrupt, see genFunction */
3930         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3931         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3932         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3933       }
3934 //      _G.interruptvector = 0;         /* sanity check */
3935
3936
3937       /* if debug then send end of function */
3938 /*      if (options.debug && currFunc)  */
3939       if (currFunc) {
3940         debugFile->writeEndFunction (currFunc, ic, 1);
3941       }
3942         
3943       if(_G.usefastretfie)
3944         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3945       else
3946         pic16_emitpcodeNULLop(POC_RETFIE);
3947
3948       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3949       
3950       _G.usefastretfie = 0;
3951       return;
3952     }
3953
3954     if (IFFUNC_ISCRITICAL(sym->type)) {
3955       pic16_emitcode("setb","ea");
3956     }
3957
3958     /* if debug then send end of function */
3959     if (currFunc) {
3960       debugFile->writeEndFunction (currFunc, ic, 1);
3961     }
3962
3963     /* insert code to restore stack frame, if user enabled it
3964      * and function is not main() */
3965          
3966
3967     pic16_emitpcodeNULLop(POC_RETURN);
3968
3969     /* Mark the end of a function */
3970     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3971 }
3972
3973
3974 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3975 {
3976   unsigned long lit=1;
3977   operand *op;
3978
3979     op = IC_LEFT(ic);
3980   
3981     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3982     if(AOP_TYPE(op) == AOP_LIT) {
3983       if(!IS_FLOAT(operandType( op ))) {
3984         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3985       } else {
3986         union {
3987           unsigned long lit_int;
3988           float lit_float;
3989         } info;
3990         
3991         /* take care if literal is a float */
3992         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3993         lit = info.lit_int;
3994       }
3995     }
3996
3997     if(is_LitOp(op)) {
3998       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3999         pic16_emitpcode(POC_CLRF, dest);
4000       } else {
4001         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4002         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4003       }
4004     } else {
4005       if(dest->type == PO_WREG && (offset == 0)) {
4006         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4007       return;
4008     }
4009     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4010   }
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genRet - generate code for return statement                     */
4015 /*-----------------------------------------------------------------*/
4016 static void genRet (iCode *ic)
4017 {
4018   int size;
4019   operand *left;
4020
4021     FENTRY;
4022         /* if we have no return value then
4023          * just generate the "ret" */
4024         
4025         if (!IC_LEFT(ic)) 
4026                 goto jumpret;       
4027     
4028         /* we have something to return then
4029          * move the return value into place */
4030         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4031         size = AOP_SIZE(IC_LEFT(ic));
4032
4033         if(size <= 4) {
4034           if(size>3)
4035             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4036           
4037           if(size>2)
4038             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4039
4040           if(size>1)
4041             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4042           
4043           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4044
4045         } else {
4046                 /* >32-bits, setup stack and FSR0 */
4047                 while (size--) {
4048 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4049 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4050
4051                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4052
4053 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4054                         GpsuedoStkPtr++;
4055                 }
4056                         
4057                 /* setup FSR0 */
4058                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4059                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4060
4061                 if(STACK_MODEL_LARGE) {
4062                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4063                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4064                 } else {
4065                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4066                 }
4067         }
4068                                 
4069 #if 0
4070         /* old code, left here for reference -- VR */    
4071         while (size--) {
4072           char *l ;
4073
4074                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4075                         /* #NOCHANGE */
4076                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4077                         pic16_emitpcomment("push %s",l);
4078                         pushed++;
4079                 } else {
4080                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4081                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4082                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4083                         
4084                         if (strcmp(fReturn[offset],l)) {
4085                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4086                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4087                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4088                                 } else {
4089                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4090                                 }
4091                                 
4092                                 if(size) {
4093                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4094                                 }
4095                                 offset++;
4096                         }
4097                 }
4098         }    
4099
4100         if (pushed) {
4101                 while(pushed) {
4102                         pushed--;
4103                         if (strcmp(fReturn[pushed],"a"))
4104                                 pic16_emitcode("pop",fReturn[pushed]);
4105                         else
4106                                 pic16_emitcode("pop","acc");
4107                 }
4108         }
4109 #endif
4110
4111
4112         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4113     
4114 jumpret:
4115         /* generate a jump to the return label
4116          * if the next is not the return statement */
4117         if (!(ic->next && ic->next->op == LABEL
4118                 && IC_LABEL(ic->next) == returnLabel)) {
4119         
4120                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4121                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4122         }
4123 }
4124
4125 /*-----------------------------------------------------------------*/
4126 /* genLabel - generates a label                                    */
4127 /*-----------------------------------------------------------------*/
4128 static void genLabel (iCode *ic)
4129 {
4130   FENTRY;
4131
4132   /* special case never generate */
4133   if (IC_LABEL(ic) == entryLabel)
4134     return ;
4135
4136   pic16_emitpLabel(IC_LABEL(ic)->key);
4137 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genGoto - generates a goto                                      */
4142 /*-----------------------------------------------------------------*/
4143 //tsd
4144 static void genGoto (iCode *ic)
4145 {
4146   FENTRY;
4147   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4148 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4149 }
4150
4151
4152 /*-----------------------------------------------------------------*/
4153 /* genMultbits :- multiplication of bits                           */
4154 /*-----------------------------------------------------------------*/
4155 static void genMultbits (operand *left, 
4156                          operand *right, 
4157                          operand *result)
4158 {
4159   FENTRY;
4160
4161   if(!pic16_sameRegs(AOP(result),AOP(right)))
4162     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4163
4164   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4165   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4166   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4167
4168 }
4169
4170
4171 /*-----------------------------------------------------------------*/
4172 /* genMultOneByte : 8 bit multiplication & division                */
4173 /*-----------------------------------------------------------------*/
4174 static void genMultOneByte (operand *left,
4175                             operand *right,
4176                             operand *result)
4177 {
4178
4179   FENTRY;
4180   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4181   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4182
4183   /* (if two literals, the value is computed before) */
4184   /* if one literal, literal on the right */
4185   if (AOP_TYPE(left) == AOP_LIT){
4186     operand *t = right;
4187     right = left;
4188     left = t;
4189   }
4190
4191         /* size is already checked in genMult == 1 */
4192 //      size = AOP_SIZE(result);
4193
4194         if (AOP_TYPE(right) == AOP_LIT){
4195                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4196                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4197                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4198                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4199         } else {
4200                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4201                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4202                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4203                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4204         }
4205         
4206         pic16_genMult8X8_8 (left, right,result);
4207 }
4208
4209 /*-----------------------------------------------------------------*/
4210 /* genMultOneWord : 16 bit multiplication                          */
4211 /*-----------------------------------------------------------------*/
4212 static void genMultOneWord (operand *left,
4213                             operand *right,
4214                             operand *result)
4215 {
4216   FENTRY;
4217   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4218   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4219
4220   /* (if two literals, the value is computed before)
4221    * if one literal, literal on the right */
4222   if (AOP_TYPE(left) == AOP_LIT){
4223     operand *t = right;
4224     right = left;
4225     left = t;
4226   }
4227
4228   /* size is checked already == 2 */
4229 //  size = AOP_SIZE(result);
4230
4231   if (AOP_TYPE(right) == AOP_LIT) {
4232     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4233       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4234       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4235       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4236   } else {
4237     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4238       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4239       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4240       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4241   }
4242         
4243   pic16_genMult16X16_16(left, right,result);
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* genMultOneLong : 32 bit multiplication                          */
4248 /*-----------------------------------------------------------------*/
4249 static void genMultOneLong (operand *left,
4250                             operand *right,
4251                             operand *result)
4252 {
4253   FENTRY;
4254   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4255   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4256
4257   /* (if two literals, the value is computed before)
4258    * if one literal, literal on the right */
4259   if (AOP_TYPE(left) == AOP_LIT){
4260     operand *t = right;
4261     right = left;
4262     left = t;
4263   }
4264
4265   /* size is checked already == 4 */
4266 //  size = AOP_SIZE(result);
4267
4268   if (AOP_TYPE(right) == AOP_LIT) {
4269     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4270         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4271         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4272         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4273   } else {
4274     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4275         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4276         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4277         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4278   }
4279         
4280   pic16_genMult32X32_32(left, right,result);
4281 }
4282
4283
4284
4285 /*-----------------------------------------------------------------*/
4286 /* genMult - generates code for multiplication                     */
4287 /*-----------------------------------------------------------------*/
4288 static void genMult (iCode *ic)
4289 {
4290   operand *left = IC_LEFT(ic);
4291   operand *right = IC_RIGHT(ic);
4292   operand *result= IC_RESULT(ic);   
4293
4294     FENTRY;
4295         /* assign the amsops */
4296         pic16_aopOp (left,ic,FALSE);
4297         pic16_aopOp (right,ic,FALSE);
4298         pic16_aopOp (result,ic,TRUE);
4299
4300         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4301
4302         /* special cases first *
4303         * both are bits */
4304         if (AOP_TYPE(left) == AOP_CRY
4305                 && AOP_TYPE(right)== AOP_CRY) {
4306                 genMultbits(left,right,result);
4307           goto release ;
4308         }
4309
4310         /* if both are of size == 1 */
4311         if(AOP_SIZE(left) == 1
4312                 && AOP_SIZE(right) == 1) {
4313                 genMultOneByte(left,right,result);
4314           goto release ;
4315         }
4316
4317         /* if both are of size == 2 */
4318         if(AOP_SIZE(left) == 2
4319                 && AOP_SIZE(right) == 2) {
4320                 genMultOneWord(left, right, result);
4321           goto release;
4322         }
4323         
4324         /* if both are of size == 4 */
4325         if(AOP_SIZE(left) == 4
4326                 && AOP_SIZE(right) == 4) {
4327                 genMultOneLong(left, right, result);
4328           goto release;
4329         }
4330         
4331         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4332
4333
4334         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4335         /* should have been converted to function call */
4336         assert(0) ;
4337
4338 release :
4339         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4341         pic16_freeAsmop(result,NULL,ic,TRUE); 
4342 }
4343
4344 /*-----------------------------------------------------------------*/
4345 /* genDivbits :- division of bits                                  */
4346 /*-----------------------------------------------------------------*/
4347 static void genDivbits (operand *left, 
4348                         operand *right, 
4349                         operand *result)
4350 {
4351   char *l;
4352
4353     FENTRY;
4354     /* the result must be bit */    
4355     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4356     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4357
4358     MOVA(l);    
4359
4360     pic16_emitcode("div","ab");
4361     pic16_emitcode("rrc","a");
4362     pic16_aopPut(AOP(result),"c",0);
4363 }
4364
4365 /*-----------------------------------------------------------------*/
4366 /* genDivOneByte : 8 bit division                                  */
4367 /*-----------------------------------------------------------------*/
4368 static void genDivOneByte (operand *left,
4369                            operand *right,
4370                            operand *result)
4371 {
4372   sym_link *opetype = operandType(result);
4373   char *l ;
4374   symbol *lbl ;
4375   int size,offset;
4376
4377         /* result = divident / divisor
4378          * - divident may be a register or a literal,
4379          * - divisor may be a register or a literal,
4380          * so there are 3 cases (literal / literal is optimized
4381          * by the front-end) to handle.
4382          * In addition we must handle signed and unsigned, which
4383          * result in 6 final different cases -- VR */
4384
4385     FENTRY;
4386     
4387     size = AOP_SIZE(result) - 1;
4388     offset = 1;
4389     /* signed or unsigned */
4390     if (SPEC_USIGN(opetype)) {
4391       pCodeOp *pct1,    /* count */
4392                 *pct2,  /* reste */
4393                 *pct3;  /* temp */
4394       symbol *label1, *label2, *label3;;
4395
4396
4397         /* unsigned is easy */
4398
4399         pct1 = pic16_popGetTempReg(1);
4400         pct2 = pic16_popGetTempReg(1);
4401         pct3 = pic16_popGetTempReg(1);
4402         
4403         label1 = newiTempLabel(NULL);
4404         label2 = newiTempLabel(NULL);
4405         label3 = newiTempLabel(NULL);
4406
4407         /* the following algorithm is extracted from divuint.c */
4408
4409         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4410         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4411         
4412         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4413
4414         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4415         
4416         pic16_emitpLabel(label1->key);
4417         
4418         emitCLRC;
4419         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4420
4421
4422         emitCLRC;
4423         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4424         
4425
4426         emitSKPNC;
4427         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4428         
4429         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4430         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4431         
4432         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4433         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4434         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4435         
4436         pic16_emitpLabel( label3->key );
4437         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4438         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4439         
4440         
4441
4442         pic16_emitpLabel(label2->key);
4443         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4444         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4445         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4446         
4447         /* result is in wreg */
4448         if(AOP_TYPE(result) != AOP_ACC)
4449                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4450
4451         pic16_popReleaseTempReg( pct3, 1);
4452         pic16_popReleaseTempReg( pct2, 1);
4453         pic16_popReleaseTempReg( pct1, 1);
4454
4455         return ;
4456     }
4457
4458     /* signed is a little bit more difficult */
4459
4460     /* save the signs of the operands */
4461     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4462     MOVA(l);    
4463     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4464     pic16_emitcode("push","acc"); /* save it on the stack */
4465
4466     /* now sign adjust for both left & right */
4467     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4468     MOVA(l);       
4469     lbl = newiTempLabel(NULL);
4470     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4471     pic16_emitcode("cpl","a");   
4472     pic16_emitcode("inc","a");
4473     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4474     pic16_emitcode("mov","b,a");
4475
4476     /* sign adjust left side */
4477     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4478     MOVA(l);
4479
4480     lbl = newiTempLabel(NULL);
4481     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4482     pic16_emitcode("cpl","a");
4483     pic16_emitcode("inc","a");
4484     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4485
4486     /* now the division */
4487     pic16_emitcode("div","ab");
4488     /* we are interested in the lower order
4489     only */
4490     pic16_emitcode("mov","b,a");
4491     lbl = newiTempLabel(NULL);
4492     pic16_emitcode("pop","acc");   
4493     /* if there was an over flow we don't 
4494     adjust the sign of the result */
4495     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4496     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4497     CLRC;
4498     pic16_emitcode("clr","a");
4499     pic16_emitcode("subb","a,b");
4500     pic16_emitcode("mov","b,a");
4501     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4502
4503     /* now we are done */
4504     pic16_aopPut(AOP(result),"b",0);
4505     if(size > 0){
4506         pic16_emitcode("mov","c,b.7");
4507         pic16_emitcode("subb","a,acc");   
4508     }
4509     while (size--)
4510         pic16_aopPut(AOP(result),"a",offset++);
4511
4512 }
4513
4514 /*-----------------------------------------------------------------*/
4515 /* genDiv - generates code for division                            */
4516 /*-----------------------------------------------------------------*/
4517 static void genDiv (iCode *ic)
4518 {
4519     operand *left = IC_LEFT(ic);
4520     operand *right = IC_RIGHT(ic);
4521     operand *result= IC_RESULT(ic);   
4522
4523
4524         /* Division is a very lengthy algorithm, so it is better
4525          * to call support routines than inlining algorithm.
4526          * Division functions written here just in case someone
4527          * wants to inline and not use the support libraries -- VR */
4528
4529     FENTRY;
4530     
4531     /* assign the amsops */
4532     pic16_aopOp (left,ic,FALSE);
4533     pic16_aopOp (right,ic,FALSE);
4534     pic16_aopOp (result,ic,TRUE);
4535
4536     /* special cases first */
4537     /* both are bits */
4538     if (AOP_TYPE(left) == AOP_CRY &&
4539         AOP_TYPE(right)== AOP_CRY) {
4540         genDivbits(left,right,result);
4541         goto release ;
4542     }
4543
4544     /* if both are of size == 1 */
4545     if (AOP_SIZE(left) == 1 &&
4546         AOP_SIZE(right) == 1 ) {
4547         genDivOneByte(left,right,result);
4548         goto release ;
4549     }
4550
4551     /* should have been converted to function call */
4552     assert(0);
4553 release :
4554     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4555     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4556     pic16_freeAsmop(result,NULL,ic,TRUE); 
4557 }
4558
4559 /*-----------------------------------------------------------------*/
4560 /* genModbits :- modulus of bits                                   */
4561 /*-----------------------------------------------------------------*/
4562 static void genModbits (operand *left, 
4563                         operand *right, 
4564                         operand *result)
4565 {
4566   char *l;
4567
4568     FENTRY;  
4569     
4570     werror(W_POSSBUG2, __FILE__, __LINE__);
4571     /* the result must be bit */    
4572     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4573     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4574
4575     MOVA(l);       
4576
4577     pic16_emitcode("div","ab");
4578     pic16_emitcode("mov","a,b");
4579     pic16_emitcode("rrc","a");
4580     pic16_aopPut(AOP(result),"c",0);
4581 }
4582
4583 /*-----------------------------------------------------------------*/
4584 /* genModOneByte : 8 bit modulus                                   */
4585 /*-----------------------------------------------------------------*/
4586 static void genModOneByte (operand *left,
4587                            operand *right,
4588                            operand *result)
4589 {
4590   sym_link *opetype = operandType(result);
4591   char *l ;
4592   symbol *lbl ;
4593
4594     FENTRY;
4595     werror(W_POSSBUG2, __FILE__, __LINE__);
4596
4597     /* signed or unsigned */
4598     if (SPEC_USIGN(opetype)) {
4599         /* unsigned is easy */
4600         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4601         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4602         MOVA(l);    
4603         pic16_emitcode("div","ab");
4604         pic16_aopPut(AOP(result),"b",0);
4605         return ;
4606     }
4607
4608     /* signed is a little bit more difficult */
4609
4610     /* save the signs of the operands */
4611     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4612     MOVA(l);
4613
4614     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4615     pic16_emitcode("push","acc"); /* save it on the stack */
4616
4617     /* now sign adjust for both left & right */
4618     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4619     MOVA(l);
4620
4621     lbl = newiTempLabel(NULL);
4622     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4623     pic16_emitcode("cpl","a");   
4624     pic16_emitcode("inc","a");
4625     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4626     pic16_emitcode("mov","b,a"); 
4627
4628     /* sign adjust left side */
4629     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4630     MOVA(l);
4631
4632     lbl = newiTempLabel(NULL);
4633     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4634     pic16_emitcode("cpl","a");   
4635     pic16_emitcode("inc","a");
4636     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4637
4638     /* now the multiplication */
4639     pic16_emitcode("div","ab");
4640     /* we are interested in the lower order
4641     only */
4642     lbl = newiTempLabel(NULL);
4643     pic16_emitcode("pop","acc");   
4644     /* if there was an over flow we don't 
4645     adjust the sign of the result */
4646     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4647     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4648     CLRC ;
4649     pic16_emitcode("clr","a");
4650     pic16_emitcode("subb","a,b");
4651     pic16_emitcode("mov","b,a");
4652     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4653
4654     /* now we are done */
4655     pic16_aopPut(AOP(result),"b",0);
4656
4657 }
4658
4659 /*-----------------------------------------------------------------*/
4660 /* genMod - generates code for division                            */
4661 /*-----------------------------------------------------------------*/
4662 static void genMod (iCode *ic)
4663 {
4664   operand *left = IC_LEFT(ic);
4665   operand *right = IC_RIGHT(ic);
4666   operand *result= IC_RESULT(ic);  
4667
4668     FENTRY;
4669     
4670     /* assign the amsops */
4671     pic16_aopOp (left,ic,FALSE);
4672     pic16_aopOp (right,ic,FALSE);
4673     pic16_aopOp (result,ic,TRUE);
4674
4675     /* special cases first */
4676     /* both are bits */
4677     if (AOP_TYPE(left) == AOP_CRY &&
4678         AOP_TYPE(right)== AOP_CRY) {
4679         genModbits(left,right,result);
4680         goto release ;
4681     }
4682
4683     /* if both are of size == 1 */
4684     if (AOP_SIZE(left) == 1 &&
4685         AOP_SIZE(right) == 1 ) {
4686         genModOneByte(left,right,result);
4687         goto release ;
4688     }
4689
4690     /* should have been converted to function call */
4691     assert(0);
4692
4693 release :
4694     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4695     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4696     pic16_freeAsmop(result,NULL,ic,TRUE); 
4697 }
4698
4699 /*-----------------------------------------------------------------*/
4700 /* genIfxJump :- will create a jump depending on the ifx           */
4701 /*-----------------------------------------------------------------*/
4702 /*
4703   note: May need to add parameter to indicate when a variable is in bit space.
4704 */
4705 static void genIfxJump (iCode *ic, char *jval)
4706 {
4707   FENTRY;
4708   
4709     /* if true label then we jump if condition
4710     supplied is true */
4711     if ( IC_TRUE(ic) ) {
4712
4713         if(strcmp(jval,"a") == 0)
4714           emitSKPZ;
4715         else if (strcmp(jval,"c") == 0)
4716           emitSKPNC;
4717         else {
4718           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4719           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4720         }
4721
4722         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4723         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4724
4725     }
4726     else {
4727         /* false label is present */
4728         if(strcmp(jval,"a") == 0)
4729           emitSKPNZ;
4730         else if (strcmp(jval,"c") == 0)
4731           emitSKPC;
4732         else {
4733           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4734           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4735         }
4736
4737         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4738         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4739
4740     }
4741
4742
4743     /* mark the icode as generated */
4744     ic->generated = 1;
4745 }
4746
4747 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4748 {
4749   FENTRY;
4750   
4751     /* if true label then we jump if condition
4752     supplied is true */
4753     if ( IC_TRUE(ic) ) {
4754       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4755       pic16_emitpcode(POC_BTFSC, jop);
4756
4757       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4758       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4759
4760     } else {
4761       /* false label is present */
4762       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4763       pic16_emitpcode(POC_BTFSS, jop);
4764           
4765       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4766       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4767     }
4768
4769
4770     /* mark the icode as generated */
4771     ic->generated = 1;
4772 }
4773
4774 #if 0
4775 // not needed ATM
4776
4777 /*-----------------------------------------------------------------*/
4778 /* genSkip                                                         */
4779 /*-----------------------------------------------------------------*/
4780 static void genSkip(iCode *ifx,int status_bit)
4781 {
4782   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4783   if(!ifx)
4784     return;
4785
4786   if ( IC_TRUE(ifx) ) {
4787     switch(status_bit) {
4788     case 'z':
4789       emitSKPNZ;
4790       break;
4791
4792     case 'c':
4793       emitSKPNC;
4794       break;
4795
4796     case 'd':
4797       emitSKPDC;
4798       break;
4799
4800     }
4801
4802     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4803     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4804
4805   } else {
4806
4807     switch(status_bit) {
4808
4809     case 'z':
4810       emitSKPZ;
4811       break;
4812
4813     case 'c':
4814       emitSKPC;
4815       break;
4816
4817     case 'd':
4818       emitSKPDC;
4819       break;
4820     }
4821     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4822     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4823
4824   }
4825
4826 }
4827 #endif
4828
4829 /*-----------------------------------------------------------------*/
4830 /* genSkipc                                                        */
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipc(resolvedIfx *rifx)
4833 {
4834   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4835   
4836   if(!rifx)
4837     return;
4838
4839   if(rifx->condition)
4840     emitSKPC;
4841   else
4842     emitSKPNC;
4843
4844   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4845   rifx->generated = 1;
4846 }
4847
4848 #if !(USE_SIMPLE_GENCMP)
4849 /*-----------------------------------------------------------------*/
4850 /* genSkipz2                                                       */
4851 /*-----------------------------------------------------------------*/
4852 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4853 {
4854   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4855   
4856   if(!rifx)
4857     return;
4858
4859   if( (rifx->condition ^ invert_condition) & 1)
4860     emitSKPZ;
4861   else
4862     emitSKPNZ;
4863
4864   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4865   rifx->generated = 1;
4866 }
4867 #endif
4868
4869 #if 0
4870 /*-----------------------------------------------------------------*/
4871 /* genSkipz                                                        */
4872 /*-----------------------------------------------------------------*/
4873 static void genSkipz(iCode *ifx, int condition)
4874 {
4875   if(!ifx)
4876     return;
4877
4878   if(condition)
4879     emitSKPNZ;
4880   else
4881     emitSKPZ;
4882
4883   if ( IC_TRUE(ifx) )
4884     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4885   else
4886     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4887
4888   if ( IC_TRUE(ifx) )
4889     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4890   else
4891     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4892
4893 }
4894 #endif
4895
4896 #if !(USE_SIMPLE_GENCMP)
4897 /*-----------------------------------------------------------------*/
4898 /* genSkipCond                                                     */
4899 /*-----------------------------------------------------------------*/
4900 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4901 {
4902   if(!rifx)
4903     return;
4904
4905   if(rifx->condition)
4906     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4907   else
4908     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4909
4910
4911   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4912   rifx->generated = 1;
4913 }
4914 #endif
4915
4916 #if 0
4917 /*-----------------------------------------------------------------*/
4918 /* genChkZeroes :- greater or less than comparison                 */
4919 /*     For each byte in a literal that is zero, inclusive or the   */
4920 /*     the corresponding byte in the operand with W                */
4921 /*     returns true if any of the bytes are zero                   */
4922 /*-----------------------------------------------------------------*/
4923 static int genChkZeroes(operand *op, int lit,  int size)
4924 {
4925
4926   int i;
4927   int flag =1;
4928
4929   while(size--) {
4930     i = (lit >> (size*8)) & 0xff;
4931
4932     if(i==0) {
4933       if(flag) 
4934         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4935       else
4936         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4937       flag = 0;
4938     }
4939   }
4940
4941   return (flag==0);
4942 }
4943 #endif
4944
4945
4946 /*-----------------------------------------------------------------*/
4947 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4948 /*                  aop (if it's NOT a literal) or from lit (if    */
4949 /*                  aop is a literal)                              */
4950 /*-----------------------------------------------------------------*/
4951 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4952   if (aop->type == AOP_LIT) {
4953     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4954   } else {
4955     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4956   }
4957 }
4958
4959 /*-----------------------------------------------------------------*/
4960 /* genCmp :- greater or less than comparison                       */
4961 /*-----------------------------------------------------------------*/
4962
4963 #if USE_SIMPLE_GENCMP           /* { */
4964
4965 /* genCmp performs a left < right comparison, stores
4966  * the outcome in result (if != NULL) and generates
4967  * control flow code for the ifx (if != NULL).
4968  *
4969  * This version leaves in sequences like
4970  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4971  * which should be optmized by the peephole
4972  * optimizer - RN 2005-01-01 */
4973 static void genCmp (operand *left,operand *right,
4974                     operand *result, iCode *ifx, int sign)
4975 {
4976   resolvedIfx rIfx;
4977   int size;
4978   int offs;
4979   symbol *templbl;
4980   operand *dummy;
4981   unsigned long lit;
4982   unsigned long mask;
4983   int performedLt;
4984
4985   FENTRY;
4986   
4987   assert (AOP_SIZE(left) == AOP_SIZE(right));
4988   assert (left && right);
4989
4990   size = AOP_SIZE(right) - 1;
4991   mask = (0x100UL << (size*8)) - 1;
4992   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4993   performedLt = 1;
4994   templbl = NULL;
4995   lit = 0;
4996   
4997   resolveIfx (&rIfx, ifx);
4998
4999   /* handle for special cases */
5000   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5001       return;
5002
5003   /**********************************************************************
5004    * handle bits - bit compares are promoted to int compares seemingly! *
5005    **********************************************************************/
5006 #if 0
5007   // THIS IS COMPLETELY UNTESTED!
5008   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5009     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5010     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5011     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5012
5013     emitSETC;
5014     // 1 < {0,1} is false --> clear C by skipping the next instruction
5015     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5016     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5017     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5018     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5019     emitCLRC; // only skipped for left=0 && right=1
5020
5021     goto correct_result_in_carry;
5022   } // if
5023 #endif
5024
5025   /*************************************************
5026    * make sure that left is register (or the like) *
5027    *************************************************/
5028   if (!isAOP_REGlike(left)) {
5029     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5030     assert (isAOP_LIT(left));
5031     assert (isAOP_REGlike(right));
5032     // swap left and right
5033     // left < right <==> right > left <==> (right >= left + 1)
5034     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5035
5036     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5037       // MAXVALUE < right? always false
5038       if (performedLt) emitCLRC; else emitSETC;
5039       goto correct_result_in_carry;
5040     } // if
5041
5042     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5043     // that's we handled it above.
5044     lit++;
5045
5046     dummy = left;
5047     left = right;
5048     right = dummy;
5049
5050     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5051   } else if (isAOP_LIT(right)) {
5052     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5053   } // if
5054
5055   assert (isAOP_REGlike(left)); // left must be register or the like
5056   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5057
5058   /*************************************************
5059    * special cases go here                         *
5060    *************************************************/
5061
5062   if (isAOP_LIT(right)) {
5063     if (!sign) {
5064       // unsigned comparison to a literal
5065       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5066       if (lit == 0) {
5067         // unsigned left < 0? always false
5068         if (performedLt) emitCLRC; else emitSETC;
5069         goto correct_result_in_carry;
5070       }
5071     } else {
5072       // signed comparison to a literal
5073       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5074       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5075         // signed left < 0x80000000? always false
5076         if (performedLt) emitCLRC; else emitSETC;
5077         goto correct_result_in_carry;
5078       } else if (lit == 0) {
5079         // compare left < 0; set CARRY if SIGNBIT(left) is set
5080         if (performedLt) emitSETC; else emitCLRC;
5081         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5082         if (performedLt) emitCLRC; else emitSETC;
5083         goto correct_result_in_carry;
5084       }
5085     } // if (!sign)
5086   } // right is literal
5087
5088   /*************************************************
5089    * perform a general case comparison             *
5090    * make sure we get CARRY==1 <==> left >= right  *
5091    *************************************************/
5092   // compare most significant bytes
5093   //DEBUGpc ("comparing bytes at offset %d", size);
5094   if (!sign) {
5095     // unsigned comparison
5096     mov2w_regOrLit (AOP(right), lit, size);
5097     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5098   } else {
5099     // signed comparison
5100     // (add 2^n to both operands then perform an unsigned comparison)
5101     if (isAOP_LIT(right)) {
5102       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5103       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5104
5105       if (litbyte == 0x80) {
5106         // left >= 0x80 -- always true, but more bytes to come
5107         pic16_mov2w (AOP(left), size);
5108         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5109         emitSETC;
5110       } else {
5111         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5112         pic16_mov2w (AOP(left), size);
5113         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5114         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5115       } // if
5116     } else {
5117       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5118       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5119       pic16_mov2w (AOP(left), size);
5120       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5121       pic16_emitpcode (POC_MOVWF, pctemp);
5122       pic16_mov2w (AOP(right), size);
5123       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124       pic16_emitpcode (POC_SUBFW, pctemp);
5125       //pic16_popReleaseTempReg(pctemp, 1);
5126     }
5127   } // if (!sign)
5128
5129   // compare remaining bytes (treat as unsigned case from above)
5130   templbl = newiTempLabel ( NULL );
5131   offs = size;
5132   while (offs--) {
5133     //DEBUGpc ("comparing bytes at offset %d", offs);
5134     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5135     mov2w_regOrLit (AOP(right), lit, offs);
5136     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5137   } // while (offs)
5138   pic16_emitpLabel (templbl->key);
5139   goto result_in_carry;
5140
5141 result_in_carry:
5142   
5143   /****************************************************
5144    * now CARRY contains the result of the comparison: *
5145    * SUBWF sets CARRY iff                             *
5146    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5147    * (F=left, W=right)
5148    ****************************************************/
5149
5150   if (performedLt) {
5151     if (result && AOP_TYPE(result) != AOP_CRY) {
5152       // value will be stored
5153       emitTOGC;
5154     } else {
5155       // value wil only be used in the following genSkipc()
5156       rIfx.condition ^= 1;
5157     }
5158   } // if
5159
5160 correct_result_in_carry:
5161
5162   // assign result to variable (if neccessary)
5163   if (result && AOP_TYPE(result) != AOP_CRY) {
5164     //DEBUGpc ("assign result");
5165     size = AOP_SIZE(result);
5166     while (size--) {
5167       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5168     } // while
5169     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5170   } // if (result)
5171
5172   // perform conditional jump
5173   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5174   if (ifx) {
5175     //DEBUGpc ("generate control flow");
5176     rIfx.condition ^= 1;
5177     genSkipc (&rIfx);
5178     ifx->generated = 1;
5179   } // if
5180 }
5181
5182 #elif 1         /* } */
5183                 /* { */
5184       /* original code */
5185 static void genCmp (operand *left,operand *right,
5186                     operand *result, iCode *ifx, int sign)
5187 {
5188   int size; //, offset = 0 ;
5189   unsigned long lit = 0L,i = 0;
5190   resolvedIfx rFalseIfx;
5191   //  resolvedIfx rTrueIfx;
5192   symbol *truelbl;
5193   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5194 /*
5195   if(ifx) {
5196     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5197     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5198   }
5199 */
5200
5201   FENTRY;
5202   
5203   resolveIfx(&rFalseIfx,ifx);
5204   truelbl  = newiTempLabel(NULL);
5205   size = max(AOP_SIZE(left),AOP_SIZE(right));
5206
5207   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5208
5209 #define _swapp
5210
5211   /* if literal is on the right then swap with left */
5212   if ((AOP_TYPE(right) == AOP_LIT)) {
5213     operand *tmp = right ;
5214     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5215     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5216 #ifdef _swapp
5217
5218     lit = (lit - 1) & mask;
5219     right = left;
5220     left = tmp;
5221     rFalseIfx.condition ^= 1;
5222 #endif
5223
5224   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5225     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5226   }
5227
5228
5229   //if(IC_TRUE(ifx) == NULL)
5230   /* if left & right are bit variables */
5231   if (AOP_TYPE(left) == AOP_CRY &&
5232       AOP_TYPE(right) == AOP_CRY ) {
5233     assert (0 && "bit variables used in genCmp");
5234     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5235     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5236   } else {
5237     /* subtract right from left if at the
5238        end the carry flag is set then we know that
5239        left is greater than right */
5240
5241     symbol *lbl  = newiTempLabel(NULL);
5242
5243 #if 0
5244         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5245                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5246 #endif
5247
5248 #ifndef _swapp
5249     if(AOP_TYPE(right) == AOP_LIT) {
5250
5251       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5252
5253       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5254
5255       /* special cases */
5256
5257       if(lit == 0) {
5258
5259         if(sign != 0) 
5260           genSkipCond(&rFalseIfx,left,size-1,7);
5261         else 
5262           /* no need to compare to 0...*/
5263           /* NOTE: this is a de-generate compare that most certainly 
5264            *       creates some dead code. */
5265           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5266
5267         if(ifx) ifx->generated = 1;
5268         return;
5269
5270       }
5271       size--;
5272
5273       if(size == 0) {
5274         //i = (lit >> (size*8)) & 0xff;
5275         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5276         
5277         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5278
5279         i = ((0-lit) & 0xff);
5280         if(sign) {
5281           if( i == 0x81) { 
5282             /* lit is 0x7f, all signed chars are less than
5283              * this except for 0x7f itself */
5284             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5285             genSkipz2(&rFalseIfx,0);
5286           } else {
5287             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5288             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5289             genSkipc(&rFalseIfx);
5290           }
5291
5292         } else {
5293           if(lit == 1) {
5294             genSkipz2(&rFalseIfx,1);
5295           } else {
5296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5297             genSkipc(&rFalseIfx);
5298           }
5299         }
5300
5301         if(ifx) ifx->generated = 1;
5302         return;
5303       }
5304
5305       /* chars are out of the way. now do ints and longs */
5306
5307
5308       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5309         
5310       /* special cases */
5311
5312       if(sign) {
5313
5314         if(lit == 0) {
5315           genSkipCond(&rFalseIfx,left,size,7);
5316           if(ifx) ifx->generated = 1;
5317           return;
5318         }
5319
5320         if(lit <0x100) {
5321           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5322
5323           //rFalseIfx.condition ^= 1;
5324           //genSkipCond(&rFalseIfx,left,size,7);
5325           //rFalseIfx.condition ^= 1;
5326
5327           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5328           if(rFalseIfx.condition)
5329             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5330           else
5331             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5332
5333           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5334           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5335           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5336
5337           while(size > 1)
5338             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5339
5340           if(rFalseIfx.condition) {
5341             emitSKPZ;
5342             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5343
5344           } else {
5345             emitSKPNZ;
5346           }
5347
5348           genSkipc(&rFalseIfx);
5349           pic16_emitpLabel(truelbl->key);
5350           if(ifx) ifx->generated = 1;
5351           return;
5352
5353         }
5354
5355         if(size == 1) {
5356
5357           if( (lit & 0xff) == 0) {
5358             /* lower byte is zero */
5359             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5360             i = ((lit >> 8) & 0xff) ^0x80;
5361             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5362             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5363             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5364             genSkipc(&rFalseIfx);
5365
5366
5367             if(ifx) ifx->generated = 1;
5368             return;
5369
5370           }
5371         } else {
5372           /* Special cases for signed longs */
5373           if( (lit & 0xffffff) == 0) {
5374             /* lower byte is zero */
5375             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5376             i = ((lit >> 8*3) & 0xff) ^0x80;
5377             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5378             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5379             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5380             genSkipc(&rFalseIfx);
5381
5382
5383             if(ifx) ifx->generated = 1;
5384             return;
5385
5386           }
5387
5388         }
5389
5390
5391         if(lit & (0x80 << (size*8))) {
5392           /* lit is negative */
5393           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5394
5395           //genSkipCond(&rFalseIfx,left,size,7);
5396
5397           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5398
5399           if(rFalseIfx.condition)
5400             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5401           else
5402             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5403
5404
5405         } else {
5406           /* lit is positive */
5407           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5408           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5409           if(rFalseIfx.condition)
5410             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5411           else
5412             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5413
5414         }
5415
5416         /*
5417           This works, but is only good for ints.
5418           It also requires a "known zero" register.
5419           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5420           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5421           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5422           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5423           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5424           genSkipc(&rFalseIfx);
5425
5426           pic16_emitpLabel(truelbl->key);
5427           if(ifx) ifx->generated = 1;
5428           return;
5429         **/
5430           
5431         /* There are no more special cases, so perform a general compare */
5432   
5433         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5434         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5435
5436         while(size--) {
5437
5438           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5439           emitSKPNZ;
5440           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5441         }
5442         //rFalseIfx.condition ^= 1;
5443         genSkipc(&rFalseIfx);
5444
5445         pic16_emitpLabel(truelbl->key);
5446
5447         if(ifx) ifx->generated = 1;
5448         return;
5449
5450
5451       }
5452
5453
5454       /* sign is out of the way. So now do an unsigned compare */
5455       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5456
5457
5458       /* General case - compare to an unsigned literal on the right.*/
5459
5460       i = (lit >> (size*8)) & 0xff;
5461       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5462       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5463       while(size--) {
5464         i = (lit >> (size*8)) & 0xff;
5465
5466         if(i) {
5467           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5468           emitSKPNZ;
5469           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5470         } else {
5471           /* this byte of the lit is zero, 
5472            *if it's not the last then OR in the variable */
5473           if(size)
5474             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5475         }
5476       }
5477
5478
5479       pic16_emitpLabel(lbl->key);
5480 //      pic16_emitpLabel(truelbl->key);
5481       //if(emitFinalCheck)
5482       genSkipc(&rFalseIfx);
5483       if(sign)
5484         pic16_emitpLabel(truelbl->key);
5485
5486       if(ifx) ifx->generated = 1;
5487       return;
5488
5489
5490     }
5491 #endif  // _swapp
5492
5493     if(AOP_TYPE(left) == AOP_LIT) {
5494       //symbol *lbl = newiTempLabel(NULL);
5495
5496       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5497
5498
5499       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5500
5501       /* Special cases */
5502       if((lit == 0) && (sign == 0)){
5503
5504         size--;
5505         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5506         while(size) 
5507           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5508
5509         genSkipz2(&rFalseIfx,0);
5510         if(ifx) ifx->generated = 1;
5511         return;
5512       }
5513
5514       if(size==1) {
5515         /* Special cases */
5516         lit &= 0xff;
5517         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5518           /* degenerate compare can never be true */
5519           if(rFalseIfx.condition == 0)
5520             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5521
5522           if(ifx) ifx->generated = 1;
5523           return;
5524         }
5525
5526         if(sign) {
5527           /* signed comparisons to a literal byte */
5528
5529           int lp1 = (lit+1) & 0xff;
5530
5531           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5532           switch (lp1) {
5533           case 0:
5534             rFalseIfx.condition ^= 1;
5535             genSkipCond(&rFalseIfx,right,0,7);
5536             break;
5537           case 0x7f:
5538             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5539             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5540             genSkipz2(&rFalseIfx,1);
5541             break;
5542           default:
5543             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5544             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5545             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5546             rFalseIfx.condition ^= 1;
5547             genSkipc(&rFalseIfx);
5548             break;
5549           }
5550         } else {
5551           /* unsigned comparisons to a literal byte */
5552
5553           switch(lit & 0xff ) {
5554           case 0:
5555             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556             genSkipz2(&rFalseIfx,0);
5557             break;
5558           case 0x7f:
5559             rFalseIfx.condition ^= 1;
5560             genSkipCond(&rFalseIfx,right,0,7);
5561             break;
5562
5563           default:
5564             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5565             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5566             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5567             rFalseIfx.condition ^= 1;
5568             if (AOP_TYPE(result) == AOP_CRY)
5569               genSkipc(&rFalseIfx);
5570             else {
5571               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5572               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5573             }         
5574             break;
5575           }
5576         }
5577
5578         if(ifx) ifx->generated = 1;
5579         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5580                 goto check_carry;
5581         return;
5582
5583       } else {
5584
5585         /* Size is greater than 1 */
5586
5587         if(sign) {
5588           int lp1 = lit+1;
5589
5590           size--;
5591
5592           if(lp1 == 0) {
5593             /* this means lit = 0xffffffff, or -1 */
5594
5595
5596             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5597             rFalseIfx.condition ^= 1;
5598             genSkipCond(&rFalseIfx,right,size,7);
5599             if(ifx) ifx->generated = 1;
5600
5601             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5602               goto check_carry;
5603
5604             return;
5605           }
5606
5607           if(lit == 0) {
5608             int s = size;
5609
5610             if(rFalseIfx.condition) {
5611               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5612               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5613             }
5614
5615             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5616             while(size--)
5617               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5618
5619
5620             emitSKPZ;
5621             if(rFalseIfx.condition) {
5622               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5623               pic16_emitpLabel(truelbl->key);
5624             }else {
5625               rFalseIfx.condition ^= 1;
5626               genSkipCond(&rFalseIfx,right,s,7);
5627             }
5628
5629             if(ifx) ifx->generated = 1;
5630
5631             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5632               goto check_carry;
5633
5634             return;
5635           }
5636
5637           if((size == 1) &&  (0 == (lp1&0xff))) {
5638             /* lower byte of signed word is zero */
5639             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5640             i = ((lp1 >> 8) & 0xff) ^0x80;
5641             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5642             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5643             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5644
5645             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5646               emitTOGC;
5647               if(ifx) ifx->generated = 1;
5648               goto check_carry;
5649             } else {
5650               rFalseIfx.condition ^= 1;
5651               genSkipc(&rFalseIfx);
5652               if(ifx) ifx->generated = 1;
5653             }
5654
5655             return;
5656           }
5657
5658           if(lit & (0x80 << (size*8))) {
5659             /* Lit is less than zero */
5660             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5661             //rFalseIfx.condition ^= 1;
5662             //genSkipCond(&rFalseIfx,left,size,7);
5663             //rFalseIfx.condition ^= 1;
5664             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5665             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5666
5667             if(rFalseIfx.condition)
5668               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5669             else
5670               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5671
5672
5673           } else {
5674             /* Lit is greater than or equal to zero */
5675             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5676             //rFalseIfx.condition ^= 1;
5677             //genSkipCond(&rFalseIfx,right,size,7);
5678             //rFalseIfx.condition ^= 1;
5679
5680             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5681             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5682
5683             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5684             if(rFalseIfx.condition)
5685               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5686             else
5687               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5688
5689           }
5690
5691           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5692           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5693
5694           while(size--) {
5695
5696             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5697             emitSKPNZ;
5698             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5699           }
5700           rFalseIfx.condition ^= 1;
5701           //rFalseIfx.condition = 1;
5702           genSkipc(&rFalseIfx);
5703
5704           pic16_emitpLabel(truelbl->key);
5705
5706           if(ifx) ifx->generated = 1;
5707
5708
5709           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5710             goto check_carry;
5711
5712           return;
5713           // end of if (sign)
5714         } else {
5715
5716           /* compare word or long to an unsigned literal on the right.*/
5717
5718
5719           size--;
5720           if(lit < 0xff) {
5721             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5722             switch (lit) {
5723             case 0:
5724               break; /* handled above */
5725 /*
5726             case 0xff:
5727               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5728               while(size--)
5729                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5730               genSkipz2(&rFalseIfx,0);
5731               break;
5732 */
5733             default:
5734               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5735               while(--size)
5736                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5737
5738               emitSKPZ;
5739               if(rFalseIfx.condition)
5740                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5741               else
5742                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5743
5744
5745               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5746               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5747
5748               rFalseIfx.condition ^= 1;
5749               genSkipc(&rFalseIfx);
5750             }
5751
5752             pic16_emitpLabel(truelbl->key);
5753
5754             if(ifx) ifx->generated = 1;
5755
5756             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5757               goto check_carry;
5758
5759             return;
5760           }
5761
5762
5763           lit++;
5764           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5765           i = (lit >> (size*8)) & 0xff;
5766
5767           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5768           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5769
5770           while(size--) {
5771             i = (lit >> (size*8)) & 0xff;
5772
5773             if(i) {
5774               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5775               emitSKPNZ;
5776               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5777             } else {
5778               /* this byte of the lit is zero, 
5779                * if it's not the last then OR in the variable */
5780               if(size)
5781                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5782             }
5783           }
5784
5785
5786           pic16_emitpLabel(lbl->key);
5787
5788           rFalseIfx.condition ^= 1;
5789
5790           genSkipc(&rFalseIfx);
5791         }
5792
5793         if(sign)
5794           pic16_emitpLabel(truelbl->key);
5795         if(ifx) ifx->generated = 1;
5796
5797             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5798               goto check_carry;
5799
5800         return;
5801       }
5802     }
5803     /* Compare two variables */
5804
5805     DEBUGpic16_emitcode(";sign","%d",sign);
5806
5807     size--;
5808     if(sign) {
5809       /* Sigh. thus sucks... */
5810       if(size) {
5811         pCodeOp *pctemp;
5812         
5813         pctemp = pic16_popGetTempReg(1);
5814         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5815         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5816         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5817         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5818         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5819         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5820         pic16_popReleaseTempReg(pctemp, 1);
5821       } else {
5822         /* Signed char comparison */
5823         /* Special thanks to Nikolai Golovchenko for this snippet */
5824         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5825         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5826         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5827         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5828         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5829         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5830
5831         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5832         genSkipc(&rFalseIfx);
5833           
5834         if(ifx) ifx->generated = 1;
5835
5836             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5837               goto check_carry;
5838
5839         return;
5840       }
5841
5842     } else {
5843
5844       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5845       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5846     }
5847
5848
5849     /* The rest of the bytes of a multi-byte compare */
5850     while (size) {
5851
5852       emitSKPZ;
5853       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5854       size--;
5855
5856       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5858
5859
5860     }
5861
5862     pic16_emitpLabel(lbl->key);
5863
5864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5865     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5866         (AOP_TYPE(result) == AOP_REG)) {
5867       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5868       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5869     } else {
5870       genSkipc(&rFalseIfx);
5871     }         
5872     //genSkipc(&rFalseIfx);
5873     if(ifx) ifx->generated = 1;
5874
5875
5876             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5877               goto check_carry;
5878
5879     return;
5880
5881   }
5882
5883 check_carry:
5884   if ((AOP_TYPE(result) != AOP_CRY) 
5885         && AOP_SIZE(result)) {
5886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5887
5888     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5889
5890     pic16_outBitC(result);
5891   } else {
5892     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5893     /* if the result is used in the next
5894        ifx conditional branch then generate
5895        code a little differently */
5896     if (ifx )
5897       genIfxJump (ifx,"c");
5898     else
5899       pic16_outBitC(result);
5900     /* leave the result in acc */
5901   }
5902
5903 }
5904
5905 #elif 0 /* VR version of genCmp() */    /* } else { */
5906
5907 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5908 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5909         operand *result, int offset, int invert_op)
5910 {
5911   /* add code here */
5912   
5913   /* check condition, > or < ?? */
5914   if(rIfx->condition != 0)invert_op ^= 1;
5915   
5916   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5917
5918   if(!ifx)invert_op ^= 1;
5919
5920   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5921       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5922   
5923   /* do selection */
5924   if(!invert_op)return POC_CPFSGT;
5925   else return POC_CPFSLT;
5926 }
5927
5928 static int compareAopfirstpass=1;
5929
5930 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5931             operand *oper, int offset, operand *result,
5932             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5933             symbol *tlbl)
5934 {
5935   int op;
5936   symbol *truelbl;
5937
5938   /* invert if there is a result to be loaded, in order to fit,
5939    * SETC/CLRC sequence */
5940   if(AOP_SIZE(result))invert_op ^= 1;
5941
5942 //  if(sign && !offset)invert_op ^= 1;
5943   
5944 //  if(sign)invert_op ^= 1;
5945   
5946   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5947
5948   if(AOP_SIZE(result) && compareAopfirstpass) {
5949     if(!ifx) {
5950       if(pcop2)
5951         pic16_emitpcode(POC_SETF, pcop2);
5952       else
5953         emitSETC;
5954     } else {
5955       if(pcop2)
5956         pic16_emitpcode(POC_CLRF, pcop2);
5957       else
5958         emitCLRC;
5959     }
5960   }
5961
5962   compareAopfirstpass = 0;
5963
5964       /* there is a bug when comparing operands with size > 1,
5965        * because higher bytes can be equal and test should be performed
5966        * to the next lower byte, current algorithm, considers operands
5967        * inequal in these cases! -- VR 20041107 */
5968
5969     
5970   if(pcop)
5971     pic16_emitpcode(op, pcop);
5972   else
5973     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5974
5975
5976   if((!sign || !offset) && AOP_SIZE(result)) {
5977     if(!ifx) {
5978       if(pcop2)
5979         pic16_emitpcode(POC_CLRF, pcop2);
5980         else
5981         emitCLRC;
5982     } else {
5983       if(pcop2)
5984         pic16_emitpcode(POC_SETF, pcop2);
5985       else
5986         emitSETC;
5987     }
5988     
5989     /* don't emit final branch (offset == 0) */
5990     if(offset) {
5991
5992       if(pcop2)
5993         pic16_emitpcode(POC_RRCF, pcop2);
5994
5995       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5996     }
5997   } else {
5998     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5999       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6000             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6001
6002       truelbl = newiTempLabel( NULL );
6003       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6004       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6005         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6006       else
6007         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6008       pic16_emitpLabel(truelbl->key);
6009     } else {
6010       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6011     }
6012   }
6013 }
6014
6015 static void genCmp (operand *left, operand *right,
6016                     operand *result, iCode *ifx, int sign)
6017 {
6018   int size, cmpop=1;
6019   long lit = 0L;
6020   resolvedIfx rFalseIfx;
6021   symbol *falselbl, *tlbl;
6022
6023     FENTRY;
6024     
6025     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6026
6027     resolveIfx(&rFalseIfx, ifx);
6028     size = max(AOP_SIZE(left), AOP_SIZE(right));
6029     
6030     /* if left & right are bit variables */
6031     if(AOP_TYPE(left) == AOP_CRY
6032       && AOP_TYPE(right) == AOP_CRY ) {
6033
6034         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6035         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6036         
6037         werror(W_POSSBUG2, __FILE__, __LINE__);
6038         exit(-1);
6039     }
6040     
6041     /* if literal is on the right then swap with left */
6042     if((AOP_TYPE(right) == AOP_LIT)) {
6043       operand *tmp = right ;
6044 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6045
6046         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6047
6048 //      lit = (lit - 1) & mask;
6049         right = left;
6050         left = tmp;
6051         rFalseIfx.condition ^= 1;               /* reverse compare */
6052     } else
6053     if ((AOP_TYPE(left) == AOP_LIT)) {
6054       /* float compares are handled by support functions */
6055       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6056     }
6057
6058     /* actual comparing algorithm */
6059 //    size = AOP_SIZE( right );
6060
6061     falselbl = newiTempLabel( NULL );
6062     if(AOP_TYPE(left) == AOP_LIT) {
6063       /* compare to literal */
6064       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6065       
6066       if(sign) {
6067         pCodeOp *pct, *pct2;
6068         symbol *tlbl1;
6069
6070         /* signed compare */
6071         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6072
6073         pct = pic16_popCopyReg(&pic16_pc_prodl);
6074         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6075         tlbl = newiTempLabel( NULL );
6076         
6077         /* first compare signs:
6078          *  a. if both are positive, compare just like unsigned
6079          *  b. if both are negative, invert cmpop, compare just like unsigned
6080          *  c. if different signs, determine the result directly */
6081
6082         size--;
6083
6084 #if 1
6085         /* { */
6086         tlbl1 = newiTempLabel( NULL );
6087 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6088
6089         if(lit > 0) {
6090
6091           /* literal is zero or positive:
6092            *  a. if carry is zero, too, continue compare,
6093            *  b. if carry is set, then continue depending on cmpop ^ condition:
6094            *    1. '<' return false (literal < variable),
6095            *    2. '>' return true (literal > variable) */
6096 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6097           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6098           
6099           
6100           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6101           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6102         } else 
6103         if(lit < 0) {
6104           
6105           /* literal is negative:
6106            *  a. if carry is set, too, continue compare,
6107            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6108            *    1. '<' return true (literal < variable),
6109            *    2. '>' return false (literal > variable) */
6110 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6111           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6112           
6113           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6115         }
6116 #if 1
6117         else {
6118           /* lit == 0 */
6119           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6120           
6121           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6122           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6123         }
6124 #endif
6125         
6126         
6127         pic16_emitpLabel( tlbl1->key );
6128 #endif  /* } */
6129
6130         compareAopfirstpass=1;
6131 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6132 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6133 //        pic16_emitpcode(POC_MOVWF, pct);
6134
6135 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6136         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6137 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6138         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6139
6140         /* generic case */        
6141           while( size-- ) {
6142 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6143 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6144 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6145 //            pic16_emitpcode(POC_MOVWF, pct);
6146
6147 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6148             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6149             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6150 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6152           }
6153 //        }
6154         
6155         if(ifx)ifx->generated = 1;
6156
6157         if(AOP_SIZE(result)) {
6158           pic16_emitpLabel(tlbl->key);
6159           pic16_emitpLabel(falselbl->key);
6160           pic16_outBitOp( result, pct2 );
6161         } else {
6162           pic16_emitpLabel(tlbl->key);
6163         }
6164       } else {
6165
6166
6167         /* unsigned compare */      
6168         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6169     
6170         compareAopfirstpass=1;
6171         while(size--) {
6172           
6173           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6174           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6175
6176         }
6177
6178         if(ifx)ifx->generated = 1;
6179
6180
6181         if(AOP_SIZE(result)) {
6182           pic16_emitpLabel(falselbl->key);
6183           pic16_outBitC( result );
6184         }
6185
6186       }
6187     } else {
6188       /* compare registers */
6189       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6190
6191
6192       if(sign) {
6193         pCodeOp *pct, *pct2;
6194         
6195         /* signed compare */
6196         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6197
6198         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6199         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6200         tlbl = newiTempLabel( NULL );
6201         
6202         compareAopfirstpass=1;
6203
6204         size--;
6205         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6206 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6207         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6208         pic16_emitpcode(POC_MOVWF, pct);
6209
6210         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6211 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6213
6214         /* WREG already holds left + 0x80 */
6215         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6216         
6217         while( size-- ) {
6218           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6219 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6220           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6221           pic16_emitpcode(POC_MOVWF, pct);
6222                 
6223           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6224 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6225           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6226
6227           /* WREG already holds left + 0x80 */
6228           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6229 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6230         }
6231         
6232         if(ifx)ifx->generated = 1;
6233
6234         if(AOP_SIZE(result)) {
6235           pic16_emitpLabel(tlbl->key);
6236           pic16_emitpLabel(falselbl->key);
6237           pic16_outBitOp( result, pct2 );
6238         } else {
6239           pic16_emitpLabel(tlbl->key);
6240         }
6241
6242       } else {
6243         /* unsigned compare */      
6244         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6245
6246         compareAopfirstpass=1;
6247         while(size--) {
6248           
6249           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6250           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6251
6252         }
6253
6254         if(ifx)ifx->generated = 1;
6255         if(AOP_SIZE(result)) {
6256
6257           pic16_emitpLabel(falselbl->key);
6258           pic16_outBitC( result );
6259         }
6260
6261       }
6262     }
6263 }
6264
6265 #endif  /* } */
6266
6267
6268
6269 /*-----------------------------------------------------------------*/
6270 /* genCmpGt :- greater than comparison                             */
6271 /*-----------------------------------------------------------------*/
6272 static void genCmpGt (iCode *ic, iCode *ifx)
6273 {
6274   operand *left, *right, *result;
6275   sym_link *letype , *retype;
6276   int sign ;
6277
6278     FENTRY;
6279     
6280     left = IC_LEFT(ic);
6281     right= IC_RIGHT(ic);
6282     result = IC_RESULT(ic);
6283
6284     letype = getSpec(operandType(left));
6285     retype =getSpec(operandType(right));
6286     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6287     /* assign the amsops */
6288     pic16_aopOp (left,ic,FALSE);
6289     pic16_aopOp (right,ic,FALSE);
6290     pic16_aopOp (result,ic,TRUE);
6291
6292     genCmp(right, left, result, ifx, sign);
6293
6294     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296     pic16_freeAsmop(result,NULL,ic,TRUE); 
6297 }
6298
6299 /*-----------------------------------------------------------------*/
6300 /* genCmpLt - less than comparisons                                */
6301 /*-----------------------------------------------------------------*/
6302 static void genCmpLt (iCode *ic, iCode *ifx)
6303 {
6304   operand *left, *right, *result;
6305   sym_link *letype , *retype;
6306   int sign ;
6307
6308     FENTRY;
6309
6310     left = IC_LEFT(ic);
6311     right= IC_RIGHT(ic);
6312     result = IC_RESULT(ic);
6313
6314     letype = getSpec(operandType(left));
6315     retype =getSpec(operandType(right));
6316     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6317
6318     /* assign the amsops */
6319     pic16_aopOp (left,ic,FALSE);
6320     pic16_aopOp (right,ic,FALSE);
6321     pic16_aopOp (result,ic,TRUE);
6322
6323     genCmp(left, right, result, ifx, sign);
6324
6325     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6327     pic16_freeAsmop(result,NULL,ic,TRUE); 
6328 }
6329
6330 #if 0
6331 // not needed ATM
6332 // FIXME reenable literal optimisation when the pic16 port is stable
6333
6334 /*-----------------------------------------------------------------*/
6335 /* genc16bit2lit - compare a 16 bit value to a literal             */
6336 /*-----------------------------------------------------------------*/
6337 static void genc16bit2lit(operand *op, int lit, int offset)
6338 {
6339   int i;
6340
6341   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6342   if( (lit&0xff) == 0) 
6343     i=1;
6344   else
6345     i=0;
6346
6347   switch( BYTEofLONG(lit,i)) { 
6348   case 0:
6349     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350     break;
6351   case 1:
6352     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6353     break;
6354   case 0xff:
6355     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6356     break;
6357   default:
6358     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6360   }
6361
6362   i ^= 1;
6363
6364   switch( BYTEofLONG(lit,i)) { 
6365   case 0:
6366     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6367     break;
6368   case 1:
6369     emitSKPNZ;
6370     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6371     break;
6372   case 0xff:
6373     emitSKPNZ;
6374     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   default:
6377     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6380
6381   }
6382
6383 }
6384 #endif
6385
6386 #if 0
6387 // not needed ATM
6388 /*-----------------------------------------------------------------*/
6389 /* gencjneshort - compare and jump if not equal                    */
6390 /*-----------------------------------------------------------------*/
6391 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6392 {
6393   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6394   int offset = 0;
6395   int res_offset = 0;  /* the result may be a different size then left or right */
6396   int res_size = AOP_SIZE(result);
6397   resolvedIfx rIfx;
6398   symbol *lbl, *lbl_done;
6399
6400   unsigned long lit = 0L;
6401   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6402
6403   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6404   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6405   if(result)
6406     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6407   resolveIfx(&rIfx,ifx);
6408   lbl =  newiTempLabel(NULL);
6409   lbl_done =  newiTempLabel(NULL);
6410
6411
6412   /* if the left side is a literal or 
6413      if the right is in a pointer register and left 
6414      is not */
6415   if ((AOP_TYPE(left) == AOP_LIT) || 
6416       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6417     operand *t = right;
6418     right = left;
6419     left = t;
6420   }
6421   if(AOP_TYPE(right) == AOP_LIT)
6422     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6423
6424   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6425     preserve_result = 1;
6426
6427   if(result && !preserve_result)
6428     {
6429       int i;
6430       for(i = 0; i < AOP_SIZE(result); i++)
6431         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6432     }
6433
6434
6435   /* if the right side is a literal then anything goes */
6436   if (AOP_TYPE(right) == AOP_LIT &&
6437       AOP_TYPE(left) != AOP_DIR ) {
6438     switch(size) {
6439     case 2:
6440       genc16bit2lit(left, lit, 0);
6441       emitSKPZ;
6442       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443       break;
6444     default:
6445       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6446       while (size--) {
6447         if(lit & 0xff) {
6448           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6450         } else {
6451           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6452         }
6453
6454         emitSKPZ;
6455         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6456         offset++;
6457         if(res_offset < res_size-1)
6458           res_offset++;
6459         lit >>= 8;
6460       }
6461       break;
6462     }
6463   }
6464
6465   /* if the right side is in a register or in direct space or
6466      if the left is a pointer register & right is not */    
6467   else if (AOP_TYPE(right) == AOP_REG ||
6468            AOP_TYPE(right) == AOP_DIR || 
6469            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6470            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6471     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6472     int lbl_key = lbl->key;
6473
6474     if(result) {
6475       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6476       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6477     }else {
6478       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6479       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6480               __FUNCTION__,__LINE__);
6481       return;
6482     }
6483    
6484 /*     switch(size) { */
6485 /*     case 2: */
6486 /*       genc16bit2lit(left, lit, 0); */
6487 /*       emitSKPNZ; */
6488 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6489 /*       break; */
6490 /*     default: */
6491     while (size--) {
6492       int emit_skip=1;
6493       if((AOP_TYPE(left) == AOP_DIR) && 
6494          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6495
6496         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6498
6499       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6500             
6501         switch (lit & 0xff) {
6502         case 0:
6503           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504           break;
6505         case 1:
6506           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6507           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6509           emit_skip=0;
6510           break;
6511         case 0xff:
6512           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6516           emit_skip=0;
6517           break;
6518         default:
6519           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6521         }
6522         lit >>= 8;
6523
6524       } else {
6525         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6526       }
6527       if(emit_skip) {
6528         if(AOP_TYPE(result) == AOP_CRY) {
6529           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6530           if(rIfx.condition)
6531             emitSKPNZ;
6532           else
6533             emitSKPZ;
6534           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6535         } else {
6536           /* fix me. probably need to check result size too */
6537           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6538           if(rIfx.condition)
6539             emitSKPZ;
6540           else
6541             emitSKPNZ;
6542           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6543           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6544         }
6545         if(ifx)
6546           ifx->generated=1;
6547       }
6548       emit_skip++;
6549       offset++;
6550       if(res_offset < res_size-1)
6551         res_offset++;
6552     }
6553 /*       break; */
6554 /*     } */
6555   } else if(AOP_TYPE(right) == AOP_REG &&
6556             AOP_TYPE(left) != AOP_DIR){
6557
6558     while(size--) {
6559       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6560       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6561       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6562       if(rIfx.condition)
6563         emitSKPNZ;
6564       else
6565         emitSKPZ;
6566       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6567       offset++;
6568       if(res_offset < res_size-1)
6569         res_offset++;
6570     }
6571       
6572   }else{
6573     /* right is a pointer reg need both a & b */
6574     while(size--) {
6575       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6576       if(strcmp(l,"b"))
6577         pic16_emitcode("mov","b,%s",l);
6578       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6579       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6580       offset++;
6581     }
6582   }
6583
6584   if(result && preserve_result)
6585     {
6586       int i;
6587       for(i = 0; i < AOP_SIZE(result); i++)
6588         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6589     }
6590
6591   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6592
6593   if(result && preserve_result)
6594     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6595
6596   if(!rIfx.condition)
6597     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6598
6599   pic16_emitpLabel(lbl->key);
6600
6601   if(result && preserve_result)
6602     {
6603       int i;
6604       for(i = 0; i < AOP_SIZE(result); i++)
6605         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6606
6607       pic16_emitpLabel(lbl_done->key);
6608    }
6609
6610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6611
6612   if(ifx)
6613     ifx->generated = 1;
6614 }
6615 #endif
6616
6617 #if 0
6618 /*-----------------------------------------------------------------*/
6619 /* gencjne - compare and jump if not equal                         */
6620 /*-----------------------------------------------------------------*/
6621 static void gencjne(operand *left, operand *right, iCode *ifx)
6622 {
6623     symbol *tlbl  = newiTempLabel(NULL);
6624
6625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6626     gencjneshort(left, right, lbl);
6627
6628     pic16_emitcode("mov","a,%s",one);
6629     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6630     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6631     pic16_emitcode("clr","a");
6632     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6633
6634     pic16_emitpLabel(lbl->key);
6635     pic16_emitpLabel(tlbl->key);
6636
6637 }
6638 #endif
6639
6640
6641 /*-----------------------------------------------------------------*/
6642 /* is_LitOp - check if operand has to be treated as literal        */
6643 /*-----------------------------------------------------------------*/
6644 static bool is_LitOp(operand *op)
6645 {
6646   return ((AOP_TYPE(op) == AOP_LIT)
6647       || ( (AOP_TYPE(op) == AOP_PCODE)
6648           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6649               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6650 }
6651
6652 /*-----------------------------------------------------------------*/
6653 /* is_LitAOp - check if operand has to be treated as literal        */
6654 /*-----------------------------------------------------------------*/
6655 static bool is_LitAOp(asmop *aop)
6656 {
6657   return ((aop->type == AOP_LIT)
6658       || ( (aop->type == AOP_PCODE)
6659           && ( (aop->aopu.pcop->type == PO_LITERAL)
6660               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6661 }
6662
6663
6664
6665 /*-----------------------------------------------------------------*/
6666 /* genCmpEq - generates code for equal to                          */
6667 /*-----------------------------------------------------------------*/
6668 static void genCmpEq (iCode *ic, iCode *ifx)
6669 {
6670   operand *left, *right, *result;
6671   symbol *falselbl = newiTempLabel(NULL);
6672   symbol *donelbl = newiTempLabel(NULL);
6673
6674   int preserve_result = 0;
6675   int generate_result = 0;
6676   int i=0;
6677   unsigned long lit = -1;
6678
6679   FENTRY;
6680   
6681   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6682   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6683   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6684  
6685   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6686
6687   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6688     {
6689       werror(W_POSSBUG2, __FILE__, __LINE__);
6690       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6691       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6692       goto release;
6693     }
6694
6695   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6696     {
6697       operand *tmp = right ;
6698       right = left;
6699       left = tmp;
6700     }
6701
6702   if (AOP_TYPE(right) == AOP_LIT) {
6703     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6704   }
6705
6706   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6707     preserve_result = 1;
6708
6709   if(result && AOP_SIZE(result))
6710     generate_result = 1;
6711
6712   if(generate_result && !preserve_result)
6713     {
6714       for(i = 0; i < AOP_SIZE(result); i++)
6715         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6716     }
6717
6718   for(i=0; i < AOP_SIZE(left); i++)
6719     {
6720       if(AOP_TYPE(left) != AOP_ACC)
6721         {
6722           if(is_LitOp(left))
6723             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6724           else
6725             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6726         }
6727       if(is_LitOp(right)) {
6728         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6729           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6730         }
6731       } else
6732         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6733
6734       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6735     }
6736
6737   // result == true
6738
6739   if(generate_result && preserve_result)
6740     {
6741       for(i = 0; i < AOP_SIZE(result); i++)
6742         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6743     }
6744
6745   if(generate_result)
6746     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6747
6748   if(generate_result && preserve_result)
6749     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6750
6751   if(ifx && IC_TRUE(ifx))
6752     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6753
6754   if(ifx && IC_FALSE(ifx))
6755     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6756
6757   pic16_emitpLabel(falselbl->key);
6758
6759   // result == false
6760
6761   if(ifx && IC_FALSE(ifx))
6762     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6763
6764   if(generate_result && preserve_result)
6765     {
6766       for(i = 0; i < AOP_SIZE(result); i++)
6767         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6768     }
6769
6770   pic16_emitpLabel(donelbl->key);
6771
6772   if(ifx)
6773     ifx->generated = 1;
6774
6775 release:
6776   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6777   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6778   pic16_freeAsmop(result,NULL,ic,TRUE);
6779
6780 }
6781
6782
6783 #if 0
6784 // old version kept for reference
6785
6786 /*-----------------------------------------------------------------*/
6787 /* genCmpEq - generates code for equal to                          */
6788 /*-----------------------------------------------------------------*/
6789 static void genCmpEq (iCode *ic, iCode *ifx)
6790 {
6791     operand *left, *right, *result;
6792     unsigned long lit = 0L;
6793     int size,offset=0;
6794     symbol *falselbl  = newiTempLabel(NULL);
6795
6796
6797     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6798
6799     if(ifx)
6800       DEBUGpic16_emitcode ("; ifx is non-null","");
6801     else
6802       DEBUGpic16_emitcode ("; ifx is null","");
6803
6804     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6805     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6806     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6807
6808     size = max(AOP_SIZE(left),AOP_SIZE(right));
6809
6810     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6811
6812     /* if literal, literal on the right or 
6813     if the right is in a pointer register and left 
6814     is not */
6815     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6816         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6817       operand *tmp = right ;
6818       right = left;
6819       left = tmp;
6820     }
6821
6822
6823     if(ifx && !AOP_SIZE(result)){
6824         symbol *tlbl;
6825         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6826         /* if they are both bit variables */
6827         if (AOP_TYPE(left) == AOP_CRY &&
6828             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6829                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6830             if(AOP_TYPE(right) == AOP_LIT){
6831                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6832                 if(lit == 0L){
6833                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6834                     pic16_emitcode("cpl","c");
6835                 } else if(lit == 1L) {
6836                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6837                 } else {
6838                     pic16_emitcode("clr","c");
6839                 }
6840                 /* AOP_TYPE(right) == AOP_CRY */
6841             } else {
6842                 symbol *lbl = newiTempLabel(NULL);
6843                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6845                 pic16_emitcode("cpl","c");
6846                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6847             }
6848             /* if true label then we jump if condition
6849             supplied is true */
6850             tlbl = newiTempLabel(NULL);
6851             if ( IC_TRUE(ifx) ) {
6852                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6853                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6854             } else {
6855                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6856                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6857             }
6858             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6859
6860                 {
6861                 /* left and right are both bit variables, result is carry */
6862                         resolvedIfx rIfx;
6863               
6864                         resolveIfx(&rIfx,ifx);
6865
6866                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6867                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6868                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6869                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6870                         genSkipz2(&rIfx,0);
6871                 }
6872         } else {
6873
6874                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6875
6876                         /* They're not both bit variables. Is the right a literal? */
6877                         if(AOP_TYPE(right) == AOP_LIT) {
6878                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6879             
6880                         switch(size) {
6881
6882                                 case 1:
6883                                         switch(lit & 0xff) {
6884                                                 case 1:
6885                                                                 if ( IC_TRUE(ifx) ) {
6886                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6887                                                                         emitSKPNZ;
6888                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6889                                                                 } else {
6890                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6891                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6892                                                                 }
6893                                                                 break;
6894                                                 case 0xff:
6895                                                                 if ( IC_TRUE(ifx) ) {
6896                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6897                                                                         emitSKPNZ;
6898                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6899                                                                 } else {
6900                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6901                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6902                                                                 }
6903                                                                 break;
6904                                                 default:
6905                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6906                                                                 if(lit)
6907                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6908                                                                 genSkip(ifx,'z');
6909                                         } // switch lit
6910
6911
6912                                         /* end of size == 1 */
6913                                         break;
6914               
6915                                 case 2:
6916                                         genc16bit2lit(left,lit,offset);
6917                                         genSkip(ifx,'z');
6918                                         break;
6919                                         /* end of size == 2 */
6920
6921                                 default:
6922                                         /* size is 4 */
6923                                         if(lit==0) {
6924                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6925                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6926                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6927                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6928                                                 genSkip(ifx,'z');
6929                                         } else {
6930                                                 /* search for patterns that can be optimized */
6931
6932                                                 genc16bit2lit(left,lit,0);
6933                                                 lit >>= 16;
6934                                                 if(lit) {
6935                                                                 if(IC_TRUE(ifx))
6936                                                                 emitSKPZ; // if hi word unequal
6937                                                                 else
6938                                                                 emitSKPNZ; // if hi word equal
6939                                                                 // fail early
6940                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6941                                                         genc16bit2lit(left,lit,2);
6942                                                         genSkip(ifx,'z');
6943                                                 } else {
6944                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6945                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6946                                                         genSkip(ifx,'z');
6947                                                 }
6948                                         }
6949                                                 pic16_emitpLabel(falselbl->key);
6950                                                 break;
6951
6952                         } // switch size
6953           
6954                         ifx->generated = 1;
6955                         goto release ;
6956             
6957
6958           } else if(AOP_TYPE(right) == AOP_CRY ) {
6959             /* we know the left is not a bit, but that the right is */
6960             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6961             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6962                       pic16_popGet(AOP(right),offset));
6963             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6964
6965             /* if the two are equal, then W will be 0 and the Z bit is set
6966              * we could test Z now, or go ahead and check the high order bytes if
6967              * the variable we're comparing is larger than a byte. */
6968
6969             while(--size)
6970               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6971
6972             if ( IC_TRUE(ifx) ) {
6973               emitSKPNZ;
6974               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6975               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6976             } else {
6977               emitSKPZ;
6978               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6979               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6980             }
6981
6982           } else {
6983             /* They're both variables that are larger than bits */
6984             int s = size;
6985
6986             tlbl = newiTempLabel(NULL);
6987
6988             while(size--) {
6989               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6990               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6991
6992               if ( IC_TRUE(ifx) ) {
6993                 if(size) {
6994                   emitSKPZ;
6995                 
6996                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6997
6998                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6999                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7000                 } else {
7001                   emitSKPNZ;
7002
7003                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7004
7005
7006                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7007                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7008                 }
7009               } else {
7010                 emitSKPZ;
7011
7012                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7013
7014                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7015                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7016               }
7017               offset++;
7018             }
7019             if(s>1 && IC_TRUE(ifx)) {
7020               pic16_emitpLabel(tlbl->key);
7021               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7022             }
7023           }
7024         }
7025         /* mark the icode as generated */
7026         ifx->generated = 1;
7027         goto release ;
7028     }
7029
7030     /* if they are both bit variables */
7031     if (AOP_TYPE(left) == AOP_CRY &&
7032         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7033         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7034         if(AOP_TYPE(right) == AOP_LIT){
7035             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7036             if(lit == 0L){
7037                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7038                 pic16_emitcode("cpl","c");
7039             } else if(lit == 1L) {
7040                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7041             } else {
7042                 pic16_emitcode("clr","c");
7043             }
7044             /* AOP_TYPE(right) == AOP_CRY */
7045         } else {
7046             symbol *lbl = newiTempLabel(NULL);
7047             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7049             pic16_emitcode("cpl","c");
7050             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7051         }
7052         /* c = 1 if egal */
7053         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7054             pic16_outBitC(result);
7055             goto release ;
7056         }
7057         if (ifx) {
7058             genIfxJump (ifx,"c");
7059             goto release ;
7060         }
7061         /* if the result is used in an arithmetic operation
7062         then put the result in place */
7063         pic16_outBitC(result);
7064     } else {
7065       
7066       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7067       gencjne(left,right,result,ifx);
7068 /*
7069       if(ifx) 
7070         gencjne(left,right,newiTempLabel(NULL));
7071       else {
7072         if(IC_TRUE(ifx)->key)
7073           gencjne(left,right,IC_TRUE(ifx)->key);
7074         else
7075           gencjne(left,right,IC_FALSE(ifx)->key);
7076         ifx->generated = 1;
7077         goto release ;
7078       }
7079       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7080         pic16_aopPut(AOP(result),"a",0);
7081         goto release ;
7082       }
7083
7084       if (ifx) {
7085         genIfxJump (ifx,"a");
7086         goto release ;
7087       }
7088 */
7089       /* if the result is used in an arithmetic operation
7090          then put the result in place */
7091 /*
7092       if (AOP_TYPE(result) != AOP_CRY) 
7093         pic16_outAcc(result);
7094 */
7095       /* leave the result in acc */
7096     }
7097
7098 release:
7099     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101     pic16_freeAsmop(result,NULL,ic,TRUE);
7102 }
7103 #endif
7104
7105 /*-----------------------------------------------------------------*/
7106 /* ifxForOp - returns the icode containing the ifx for operand     */
7107 /*-----------------------------------------------------------------*/
7108 static iCode *ifxForOp ( operand *op, iCode *ic )
7109 {
7110   FENTRY2;
7111
7112     /* if true symbol then needs to be assigned */
7113     if (IS_TRUE_SYMOP(op))
7114         return NULL ;
7115
7116     /* if this has register type condition and
7117     the next instruction is ifx with the same operand
7118     and live to of the operand is upto the ifx only then */
7119     if (ic->next
7120         && ic->next->op == IFX
7121         && IC_COND(ic->next)->key == op->key
7122         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7123         ) {
7124                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7125           return ic->next;
7126     }
7127
7128     /*
7129     if (ic->next &&
7130         ic->next->op == IFX &&
7131         IC_COND(ic->next)->key == op->key) {
7132       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7133       return ic->next;
7134     }
7135     */
7136
7137     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7138     if (ic->next &&
7139         ic->next->op == IFX)
7140       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7141
7142     if (ic->next &&
7143         ic->next->op == IFX &&
7144         IC_COND(ic->next)->key == op->key) {
7145       DEBUGpic16_emitcode ("; "," key is okay");
7146       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7147                            OP_SYMBOL(op)->liveTo,
7148                            ic->next->seq);
7149     }
7150
7151 #if 0
7152     /* the code below is completely untested
7153      * it just allows ulong2fs.c compile -- VR */
7154          
7155     ic = ic->next;
7156     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7157                                         __FILE__, __FUNCTION__, __LINE__);
7158         
7159     /* if this has register type condition and
7160     the next instruction is ifx with the same operand
7161     and live to of the operand is upto the ifx only then */
7162     if (ic->next &&
7163         ic->next->op == IFX &&
7164         IC_COND(ic->next)->key == op->key &&
7165         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7166         return ic->next;
7167
7168     if (ic->next &&
7169         ic->next->op == IFX &&
7170         IC_COND(ic->next)->key == op->key) {
7171       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7172       return ic->next;
7173     }
7174
7175     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7176                                         __FILE__, __FUNCTION__, __LINE__);
7177
7178 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7179 #endif
7180
7181     return NULL;
7182 }
7183 /*-----------------------------------------------------------------*/
7184 /* genAndOp - for && operation                                     */
7185 /*-----------------------------------------------------------------*/
7186 static void genAndOp (iCode *ic)
7187 {
7188   operand *left,*right, *result;
7189 /*     symbol *tlbl; */
7190
7191     FENTRY;
7192
7193     /* note here that && operations that are in an
7194     if statement are taken away by backPatchLabels
7195     only those used in arthmetic operations remain */
7196     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7197     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7198     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7199
7200     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7201
7202     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7203     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7204     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7205
7206     /* if both are bit variables */
7207 /*     if (AOP_TYPE(left) == AOP_CRY && */
7208 /*         AOP_TYPE(right) == AOP_CRY ) { */
7209 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7210 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7211 /*         pic16_outBitC(result); */
7212 /*     } else { */
7213 /*         tlbl = newiTempLabel(NULL); */
7214 /*         pic16_toBoolean(left);     */
7215 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7216 /*         pic16_toBoolean(right); */
7217 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7218 /*         pic16_outBitAcc(result); */
7219 /*     } */
7220
7221     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7222     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7223     pic16_freeAsmop(result,NULL,ic,TRUE);
7224 }
7225
7226
7227 /*-----------------------------------------------------------------*/
7228 /* genOrOp - for || operation                                      */
7229 /*-----------------------------------------------------------------*/
7230 /*
7231   tsd pic port -
7232   modified this code, but it doesn't appear to ever get called
7233 */
7234
7235 static void genOrOp (iCode *ic)
7236 {
7237   operand *left,*right, *result;
7238   symbol *tlbl;
7239
7240     FENTRY;  
7241
7242   /* note here that || operations that are in an
7243     if statement are taken away by backPatchLabels
7244     only those used in arthmetic operations remain */
7245     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7246     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7247     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7248
7249     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7250
7251     /* if both are bit variables */
7252     if (AOP_TYPE(left) == AOP_CRY &&
7253         AOP_TYPE(right) == AOP_CRY ) {
7254       pic16_emitcode("clrc","");
7255       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7256                AOP(left)->aopu.aop_dir,
7257                AOP(left)->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("setc","");
7262
7263     } else {
7264         tlbl = newiTempLabel(NULL);
7265         pic16_toBoolean(left);
7266         emitSKPZ;
7267         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7268         pic16_toBoolean(right);
7269         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7270
7271         pic16_outBitAcc(result);
7272     }
7273
7274     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7275     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7276     pic16_freeAsmop(result,NULL,ic,TRUE);            
7277 }
7278
7279 /*-----------------------------------------------------------------*/
7280 /* isLiteralBit - test if lit == 2^n                               */
7281 /*-----------------------------------------------------------------*/
7282 static int isLiteralBit(unsigned long lit)
7283 {
7284     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7285     0x100L,0x200L,0x400L,0x800L,
7286     0x1000L,0x2000L,0x4000L,0x8000L,
7287     0x10000L,0x20000L,0x40000L,0x80000L,
7288     0x100000L,0x200000L,0x400000L,0x800000L,
7289     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7290     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7291     int idx;
7292     
7293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7294     for(idx = 0; idx < 32; idx++)
7295         if(lit == pw[idx])
7296             return idx+1;
7297     return 0;
7298 }
7299
7300 /*-----------------------------------------------------------------*/
7301 /* continueIfTrue -                                                */
7302 /*-----------------------------------------------------------------*/
7303 static void continueIfTrue (iCode *ic)
7304 {
7305   FENTRY;
7306   if(IC_TRUE(ic))
7307     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7308   ic->generated = 1;
7309 }
7310
7311 /*-----------------------------------------------------------------*/
7312 /* jmpIfTrue -                                                     */
7313 /*-----------------------------------------------------------------*/
7314 static void jumpIfTrue (iCode *ic)
7315 {
7316   FENTRY;
7317   if(!IC_TRUE(ic))
7318     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7319   ic->generated = 1;
7320 }
7321
7322 /*-----------------------------------------------------------------*/
7323 /* jmpTrueOrFalse -                                                */
7324 /*-----------------------------------------------------------------*/
7325 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7326 {
7327   // ugly but optimized by peephole
7328   FENTRY;
7329   if(IC_TRUE(ic)){
7330     symbol *nlbl = newiTempLabel(NULL);
7331       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7332       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7333       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7334       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7335   } else {
7336     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7337     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7338   }
7339   ic->generated = 1;
7340 }
7341
7342 /*-----------------------------------------------------------------*/
7343 /* genAnd  - code for and                                          */
7344 /*-----------------------------------------------------------------*/
7345 static void genAnd (iCode *ic, iCode *ifx)
7346 {
7347   operand *left, *right, *result;
7348   int size, offset=0;  
7349   unsigned long lit = 0L;
7350   int bytelit = 0;
7351   resolvedIfx rIfx;
7352
7353     FENTRY;
7354     
7355   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7356   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7357   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7358
7359   resolveIfx(&rIfx,ifx);
7360
7361   /* if left is a literal & right is not then exchange them */
7362   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7363       AOP_NEEDSACC(left)) {
7364     operand *tmp = right ;
7365     right = left;
7366     left = tmp;
7367   }
7368
7369   /* if result = right then exchange them */
7370   if(pic16_sameRegs(AOP(result),AOP(right))){
7371     operand *tmp = right ;
7372     right = left;
7373     left = tmp;
7374   }
7375
7376   /* if right is bit then exchange them */
7377   if (AOP_TYPE(right) == AOP_CRY &&
7378       AOP_TYPE(left) != AOP_CRY){
7379     operand *tmp = right ;
7380     right = left;
7381     left = tmp;
7382   }
7383   if(AOP_TYPE(right) == AOP_LIT)
7384     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7385
7386   size = AOP_SIZE(result);
7387
7388   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7389
7390   // if(bit & yy)
7391   // result = bit & yy;
7392   if (AOP_TYPE(left) == AOP_CRY){
7393     // c = bit & literal;
7394     if(AOP_TYPE(right) == AOP_LIT){
7395       if(lit & 1) {
7396         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7397           // no change
7398           goto release;
7399         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7400       } else {
7401         // bit(result) = 0;
7402         if(size && (AOP_TYPE(result) == AOP_CRY)){
7403           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7404           goto release;
7405         }
7406         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7407           jumpIfTrue(ifx);
7408           goto release;
7409         }
7410         pic16_emitcode("clr","c");
7411       }
7412     } else {
7413       if (AOP_TYPE(right) == AOP_CRY){
7414         // c = bit & bit;
7415         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7416         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7417       } else {
7418         // c = bit & val;
7419         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7420         // c = lsb
7421         pic16_emitcode("rrc","a");
7422         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7423       }
7424     }
7425     // bit = c
7426     // val = c
7427     if(size)
7428       pic16_outBitC(result);
7429     // if(bit & ...)
7430     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7431       genIfxJump(ifx, "c");           
7432     goto release ;
7433   }
7434
7435   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7436   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7437   if((AOP_TYPE(right) == AOP_LIT) &&
7438      (AOP_TYPE(result) == AOP_CRY) &&
7439      (AOP_TYPE(left) != AOP_CRY)){
7440     int posbit = isLiteralBit(lit);
7441     /* left &  2^n */
7442     if(posbit){
7443       posbit--;
7444       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7445       // bit = left & 2^n
7446       if(size)
7447         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7448       // if(left &  2^n)
7449       else{
7450         if(ifx){
7451 /*
7452           if(IC_TRUE(ifx)) {
7453             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7454             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7455           } else {
7456             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7457             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7458           }
7459 */
7460         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7461         size = AOP_SIZE(left);
7462
7463         {
7464           int bp = posbit, ofs=0;
7465           
7466             while(bp > 7) {
7467               bp -= 8;
7468               ofs++;
7469             }
7470         
7471           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7472                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7473
7474         }
7475 /*
7476           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7477                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7478 */
7479           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7480           
7481           ifx->generated = 1;
7482         }
7483         goto release;
7484       }
7485     } else {
7486       symbol *tlbl = newiTempLabel(NULL);
7487       int sizel = AOP_SIZE(left);
7488
7489       if(size)
7490         emitSETC;
7491
7492       while(sizel--) {
7493         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7494
7495           /* patch provided by Aaron Colwell */
7496           if((posbit = isLiteralBit(bytelit)) != 0) {
7497               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7498                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7499                                                 (posbit-1),0, PO_GPR_REGISTER));
7500
7501               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7502 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7503           } else {
7504               if (bytelit == 0xff) {
7505                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7506                    * a peephole could optimize it out -- VR */
7507                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7508               } else {
7509                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7510                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7511               }
7512
7513               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7514                             pic16_popGetLabel(tlbl->key));
7515           }
7516         
7517 #if 0
7518           /* old code, left here for reference -- VR 09/2004 */
7519           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7520           // byte ==  2^n ?
7521           if((posbit = isLiteralBit(bytelit)) != 0)
7522             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7523           else{
7524             if(bytelit != 0x0FFL)
7525               pic16_emitcode("anl","a,%s",
7526                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7527             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7528           }
7529 #endif
7530         }
7531         offset++;
7532       }
7533       // bit = left & literal
7534       if(size) {
7535         emitCLRC;
7536         pic16_emitpLabel(tlbl->key);
7537       }
7538       // if(left & literal)
7539       else {
7540         if(ifx) {
7541           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7542           ifx->generated = 1;
7543         }
7544         pic16_emitpLabel(tlbl->key);
7545         goto release;
7546       }
7547     }
7548
7549     pic16_outBitC(result);
7550     goto release ;
7551   }
7552
7553   /* if left is same as result */
7554   if(pic16_sameRegs(AOP(result),AOP(left))){
7555     int know_W = -1;
7556     for(;size--; offset++,lit>>=8) {
7557       if(AOP_TYPE(right) == AOP_LIT){
7558         switch(lit & 0xff) {
7559         case 0x00:
7560           /*  and'ing with 0 has clears the result */
7561 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7562           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7563           break;
7564         case 0xff:
7565           /* and'ing with 0xff is a nop when the result and left are the same */
7566           break;
7567
7568         default:
7569           {
7570             int p = pic16_my_powof2( (~lit) & 0xff );
7571             if(p>=0) {
7572               /* only one bit is set in the literal, so use a bcf instruction */
7573 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7574               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7575
7576             } else {
7577               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7578               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7579               if(know_W != (lit&0xff))
7580                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7581               know_W = lit &0xff;
7582               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7583             }
7584           }    
7585         }
7586       } else {
7587         if (AOP_TYPE(left) == AOP_ACC) {
7588           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7589         } else {                    
7590           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7591           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7592
7593         }
7594       }
7595     }
7596
7597   } else {
7598     // left & result in different registers
7599     if(AOP_TYPE(result) == AOP_CRY){
7600       // result = bit
7601       // if(size), result in bit
7602       // if(!size && ifx), conditional oper: if(left & right)
7603       symbol *tlbl = newiTempLabel(NULL);
7604       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7605       if(size)
7606         pic16_emitcode("setb","c");
7607       while(sizer--){
7608         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7609         pic16_emitcode("anl","a,%s",
7610                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7611         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7612         offset++;
7613       }
7614       if(size){
7615         CLRC;
7616         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7617         pic16_outBitC(result);
7618       } else if(ifx)
7619         jmpTrueOrFalse(ifx, tlbl);
7620     } else {
7621       for(;(size--);offset++) {
7622         // normal case
7623         // result = left & right
7624         if(AOP_TYPE(right) == AOP_LIT){
7625           int t = (lit >> (offset*8)) & 0x0FFL;
7626           switch(t) { 
7627           case 0x00:
7628             pic16_emitcode("clrf","%s",
7629                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7630             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7631             break;
7632           case 0xff:
7633             pic16_emitcode("movf","%s,w",
7634                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7635             pic16_emitcode("movwf","%s",
7636                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7637             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7638             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7639             break;
7640           default:
7641             pic16_emitcode("movlw","0x%x",t);
7642             pic16_emitcode("andwf","%s,w",
7643                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7644             pic16_emitcode("movwf","%s",
7645                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7646               
7647             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7648             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7649             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7650           }
7651           continue;
7652         }
7653
7654         if (AOP_TYPE(left) == AOP_ACC) {
7655           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7656           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7657         } else {
7658           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7659           pic16_emitcode("andwf","%s,w",
7660                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7661           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7662           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7663         }
7664         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7665         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7666       }
7667     }
7668   }
7669
7670   release :
7671     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7672   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7673   pic16_freeAsmop(result,NULL,ic,TRUE);     
7674 }
7675
7676 /*-----------------------------------------------------------------*/
7677 /* genOr  - code for or                                            */
7678 /*-----------------------------------------------------------------*/
7679 static void genOr (iCode *ic, iCode *ifx)
7680 {
7681     operand *left, *right, *result;
7682     int size, offset=0;
7683     unsigned long lit = 0L;
7684
7685     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7686
7687     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7688     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7689     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7690
7691     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7692
7693     /* if left is a literal & right is not then exchange them */
7694     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7695         AOP_NEEDSACC(left)) {
7696         operand *tmp = right ;
7697         right = left;
7698         left = tmp;
7699     }
7700
7701     /* if result = right then exchange them */
7702     if(pic16_sameRegs(AOP(result),AOP(right))){
7703         operand *tmp = right ;
7704         right = left;
7705         left = tmp;
7706     }
7707
7708     /* if right is bit then exchange them */
7709     if (AOP_TYPE(right) == AOP_CRY &&
7710         AOP_TYPE(left) != AOP_CRY){
7711         operand *tmp = right ;
7712         right = left;
7713         left = tmp;
7714     }
7715
7716     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7717
7718     if(AOP_TYPE(right) == AOP_LIT)
7719         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7720
7721     size = AOP_SIZE(result);
7722
7723     // if(bit | yy)
7724     // xx = bit | yy;
7725     if (AOP_TYPE(left) == AOP_CRY){
7726         if(AOP_TYPE(right) == AOP_LIT){
7727             // c = bit & literal;
7728             if(lit){
7729                 // lit != 0 => result = 1
7730                 if(AOP_TYPE(result) == AOP_CRY){
7731                   if(size)
7732                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7733                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7734                   //     AOP(result)->aopu.aop_dir,
7735                   //     AOP(result)->aopu.aop_dir);
7736                     else if(ifx)
7737                         continueIfTrue(ifx);
7738                     goto release;
7739                 }
7740             } else {
7741                 // lit == 0 => result = left
7742                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7743                     goto release;
7744                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7745             }
7746         } else {
7747             if (AOP_TYPE(right) == AOP_CRY){
7748               if(pic16_sameRegs(AOP(result),AOP(left))){
7749                 // c = bit | bit;
7750                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7751                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7752                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7753
7754                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7755                          AOP(result)->aopu.aop_dir,
7756                          AOP(result)->aopu.aop_dir);
7757                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7758                          AOP(right)->aopu.aop_dir,
7759                          AOP(right)->aopu.aop_dir);
7760                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7761                          AOP(result)->aopu.aop_dir,
7762                          AOP(result)->aopu.aop_dir);
7763               } else {
7764                 if( AOP_TYPE(result) == AOP_ACC) {
7765                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7766                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7767                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7768                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7769
7770                 } else {
7771
7772                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7773                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7774                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7775                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7776
7777                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7778                                  AOP(result)->aopu.aop_dir,
7779                                  AOP(result)->aopu.aop_dir);
7780                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7781                                  AOP(right)->aopu.aop_dir,
7782                                  AOP(right)->aopu.aop_dir);
7783                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7784                                  AOP(left)->aopu.aop_dir,
7785                                  AOP(left)->aopu.aop_dir);
7786                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7787                                  AOP(result)->aopu.aop_dir,
7788                                  AOP(result)->aopu.aop_dir);
7789                 }
7790               }
7791             } else {
7792                 // c = bit | val;
7793                 symbol *tlbl = newiTempLabel(NULL);
7794                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7795
7796
7797                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7798                 if( AOP_TYPE(right) == AOP_ACC) {
7799                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7800                   emitSKPNZ;
7801                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7802                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7803                 }
7804
7805
7806
7807                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7808                     pic16_emitcode(";XXX setb","c");
7809                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7810                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7811                 pic16_toBoolean(right);
7812                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7813                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7814                     jmpTrueOrFalse(ifx, tlbl);
7815                     goto release;
7816                 } else {
7817                     CLRC;
7818                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7819                 }
7820             }
7821         }
7822         // bit = c
7823         // val = c
7824         if(size)
7825             pic16_outBitC(result);
7826         // if(bit | ...)
7827         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7828             genIfxJump(ifx, "c");           
7829         goto release ;
7830     }
7831
7832     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7833     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7834     if((AOP_TYPE(right) == AOP_LIT) &&
7835        (AOP_TYPE(result) == AOP_CRY) &&
7836        (AOP_TYPE(left) != AOP_CRY)){
7837         if(lit){
7838           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7839             // result = 1
7840             if(size)
7841                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7842             else 
7843                 continueIfTrue(ifx);
7844             goto release;
7845         } else {
7846           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847             // lit = 0, result = boolean(left)
7848             if(size)
7849                 pic16_emitcode(";XXX setb","c");
7850             pic16_toBoolean(right);
7851             if(size){
7852                 symbol *tlbl = newiTempLabel(NULL);
7853                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7854                 CLRC;
7855                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7856             } else {
7857                 genIfxJump (ifx,"a");
7858                 goto release;
7859             }
7860         }
7861         pic16_outBitC(result);
7862         goto release ;
7863     }
7864
7865     /* if left is same as result */
7866     if(pic16_sameRegs(AOP(result),AOP(left))){
7867       int know_W = -1;
7868       for(;size--; offset++,lit>>=8) {
7869         if(AOP_TYPE(right) == AOP_LIT){
7870           if((lit & 0xff) == 0)
7871             /*  or'ing with 0 has no effect */
7872             continue;
7873           else {
7874             int p = pic16_my_powof2(lit & 0xff);
7875             if(p>=0) {
7876               /* only one bit is set in the literal, so use a bsf instruction */
7877               pic16_emitpcode(POC_BSF,
7878                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7879             } else {
7880               if(know_W != (lit & 0xff))
7881                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7882               know_W = lit & 0xff;
7883               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7884             }
7885                     
7886           }
7887         } else {
7888           if (AOP_TYPE(left) == AOP_ACC) {
7889             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7890             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7891           } else {                  
7892             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7893             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7894
7895             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7896             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7897
7898           }
7899         }
7900       }
7901     } else {
7902         // left & result in different registers
7903         if(AOP_TYPE(result) == AOP_CRY){
7904             // result = bit
7905             // if(size), result in bit
7906             // if(!size && ifx), conditional oper: if(left | right)
7907             symbol *tlbl = newiTempLabel(NULL);
7908             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7909             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7910
7911
7912             if(size)
7913                 pic16_emitcode(";XXX setb","c");
7914             while(sizer--){
7915                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7916                 pic16_emitcode(";XXX orl","a,%s",
7917                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7918                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7919                 offset++;
7920             }
7921             if(size){
7922                 CLRC;
7923                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7924                 pic16_outBitC(result);
7925             } else if(ifx)
7926                 jmpTrueOrFalse(ifx, tlbl);
7927         } else for(;(size--);offset++){
7928           // normal case
7929           // result = left & right
7930           if(AOP_TYPE(right) == AOP_LIT){
7931             int t = (lit >> (offset*8)) & 0x0FFL;
7932             switch(t) { 
7933             case 0x00:
7934               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7935               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7936
7937               pic16_emitcode("movf","%s,w",
7938                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7939               pic16_emitcode("movwf","%s",
7940                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7941               break;
7942             default:
7943               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7944               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7945               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7946
7947               pic16_emitcode("movlw","0x%x",t);
7948               pic16_emitcode("iorwf","%s,w",
7949                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7950               pic16_emitcode("movwf","%s",
7951                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7952               
7953             }
7954             continue;
7955           }
7956
7957           // faster than result <- left, anl result,right
7958           // and better if result is SFR
7959           if (AOP_TYPE(left) == AOP_ACC) {
7960             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7961             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7962           } else {
7963             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7964             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7965
7966             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7967             pic16_emitcode("iorwf","%s,w",
7968                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7969           }
7970           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7971           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7972         }
7973     }
7974
7975 release :
7976     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7977     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7978     pic16_freeAsmop(result,NULL,ic,TRUE);     
7979 }
7980
7981 /*-----------------------------------------------------------------*/
7982 /* genXor - code for xclusive or                                   */
7983 /*-----------------------------------------------------------------*/
7984 static void genXor (iCode *ic, iCode *ifx)
7985 {
7986   operand *left, *right, *result;
7987   int size, offset=0;
7988   unsigned long lit = 0L;
7989
7990   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7991
7992   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7993   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7994   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7995
7996   /* if left is a literal & right is not ||
7997      if left needs acc & right does not */
7998   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7999       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8000     operand *tmp = right ;
8001     right = left;
8002     left = tmp;
8003   }
8004
8005   /* if result = right then exchange them */
8006   if(pic16_sameRegs(AOP(result),AOP(right))){
8007     operand *tmp = right ;
8008     right = left;
8009     left = tmp;
8010   }
8011
8012   /* if right is bit then exchange them */
8013   if (AOP_TYPE(right) == AOP_CRY &&
8014       AOP_TYPE(left) != AOP_CRY){
8015     operand *tmp = right ;
8016     right = left;
8017     left = tmp;
8018   }
8019   if(AOP_TYPE(right) == AOP_LIT)
8020     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8021
8022   size = AOP_SIZE(result);
8023
8024   // if(bit ^ yy)
8025   // xx = bit ^ yy;
8026   if (AOP_TYPE(left) == AOP_CRY){
8027     if(AOP_TYPE(right) == AOP_LIT){
8028       // c = bit & literal;
8029       if(lit>>1){
8030         // lit>>1  != 0 => result = 1
8031         if(AOP_TYPE(result) == AOP_CRY){
8032           if(size)
8033             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8034             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8035           else if(ifx)
8036             continueIfTrue(ifx);
8037           goto release;
8038         }
8039         pic16_emitcode("setb","c");
8040       } else{
8041         // lit == (0 or 1)
8042         if(lit == 0){
8043           // lit == 0, result = left
8044           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8045             goto release;
8046           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8047         } else{
8048           // lit == 1, result = not(left)
8049           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8050             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8051             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8052             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8053             goto release;
8054           } else {
8055             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8056             pic16_emitcode("cpl","c");
8057           }
8058         }
8059       }
8060
8061     } else {
8062       // right != literal
8063       symbol *tlbl = newiTempLabel(NULL);
8064       if (AOP_TYPE(right) == AOP_CRY){
8065         // c = bit ^ bit;
8066         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8067       }
8068       else{
8069         int sizer = AOP_SIZE(right);
8070         // c = bit ^ val
8071         // if val>>1 != 0, result = 1
8072         pic16_emitcode("setb","c");
8073         while(sizer){
8074           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8075           if(sizer == 1)
8076             // test the msb of the lsb
8077             pic16_emitcode("anl","a,#0xfe");
8078           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8079           sizer--;
8080         }
8081         // val = (0,1)
8082         pic16_emitcode("rrc","a");
8083       }
8084       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8085       pic16_emitcode("cpl","c");
8086       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8087     }
8088     // bit = c
8089     // val = c
8090     if(size)
8091       pic16_outBitC(result);
8092     // if(bit | ...)
8093     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8094       genIfxJump(ifx, "c");           
8095     goto release ;
8096   }
8097
8098   if(pic16_sameRegs(AOP(result),AOP(left))){
8099     /* if left is same as result */
8100     for(;size--; offset++) {
8101       if(AOP_TYPE(right) == AOP_LIT){
8102         int t  = (lit >> (offset*8)) & 0x0FFL;
8103         if(t == 0x00L)
8104           continue;
8105         else
8106           if (IS_AOP_PREG(left)) {
8107             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8108             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8109             pic16_aopPut(AOP(result),"a",offset);
8110           } else {
8111             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8112             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8113             pic16_emitcode("xrl","%s,%s",
8114                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8115                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116           }
8117       } else {
8118         if (AOP_TYPE(left) == AOP_ACC)
8119           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8120         else {
8121           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8122           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8123 /*
8124           if (IS_AOP_PREG(left)) {
8125             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8126             pic16_aopPut(AOP(result),"a",offset);
8127           } else
8128             pic16_emitcode("xrl","%s,a",
8129                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8130 */
8131         }
8132       }
8133     }
8134   } else {
8135     // left & result in different registers
8136     if(AOP_TYPE(result) == AOP_CRY){
8137       // result = bit
8138       // if(size), result in bit
8139       // if(!size && ifx), conditional oper: if(left ^ right)
8140       symbol *tlbl = newiTempLabel(NULL);
8141       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8142       if(size)
8143         pic16_emitcode("setb","c");
8144       while(sizer--){
8145         if((AOP_TYPE(right) == AOP_LIT) &&
8146            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8147           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8148         } else {
8149           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8150           pic16_emitcode("xrl","a,%s",
8151                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8152         }
8153         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8154         offset++;
8155       }
8156       if(size){
8157         CLRC;
8158         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8159         pic16_outBitC(result);
8160       } else if(ifx)
8161         jmpTrueOrFalse(ifx, tlbl);
8162     } else for(;(size--);offset++){
8163       // normal case
8164       // result = left & right
8165       if(AOP_TYPE(right) == AOP_LIT){
8166         int t = (lit >> (offset*8)) & 0x0FFL;
8167         switch(t) { 
8168         case 0x00:
8169           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8170           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8171           pic16_emitcode("movf","%s,w",
8172                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173           pic16_emitcode("movwf","%s",
8174                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8175           break;
8176         case 0xff:
8177           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8178           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179           pic16_emitcode("comf","%s,w",
8180                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181           pic16_emitcode("movwf","%s",
8182                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183           break;
8184         default:
8185           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8186           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8187           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8188           pic16_emitcode("movlw","0x%x",t);
8189           pic16_emitcode("xorwf","%s,w",
8190                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191           pic16_emitcode("movwf","%s",
8192                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193
8194         }
8195         continue;
8196       }
8197
8198       // faster than result <- left, anl result,right
8199       // and better if result is SFR
8200       if (AOP_TYPE(left) == AOP_ACC) {
8201         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8202         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8203       } else {
8204         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8205         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8206         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8207         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8208       }
8209       if ( AOP_TYPE(result) != AOP_ACC){
8210         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8211         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8212       }
8213     }
8214   }
8215
8216   release :
8217     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8218   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8219   pic16_freeAsmop(result,NULL,ic,TRUE);     
8220 }
8221
8222 /*-----------------------------------------------------------------*/
8223 /* genInline - write the inline code out                           */
8224 /*-----------------------------------------------------------------*/
8225 static void genInline (iCode *ic)
8226 {
8227   char *buffer, *bp, *bp1;
8228   char *cbuf;
8229     
8230         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8231
8232         _G.inLine += (!options.asmpeep);
8233
8234         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8235         strcpy(buffer,IC_INLINE(ic));
8236         
8237         while((bp1=strstr(bp, "\\n"))) {
8238           *bp1++ = '\n';
8239           *bp1++ = ' ';
8240           bp = bp1;
8241         }
8242         bp = bp1 = buffer;
8243
8244         cbuf = Safe_strdup( buffer );
8245
8246         if(asmInlineMap)
8247         {
8248           symbol *sym;
8249           char *s;
8250           int cblen;
8251
8252             cbuf = Safe_strdup(buffer);
8253             cblen = strlen(buffer)+1;
8254             memset(cbuf, 0, cblen);
8255
8256             bp = buffer;
8257             bp1 = cbuf;
8258             while(*bp) {
8259               if(*bp != '%')*bp1++ = *bp++;
8260               else {
8261                 int i;
8262
8263                   bp++;
8264                   i = *bp - '0';
8265                   if(i>elementsInSet(asmInlineMap))break;
8266                   
8267                   bp++;
8268                   s = indexSet(asmInlineMap, i);
8269                   DEBUGpc("searching symbol s = `%s'", s);
8270                   sym = findSym(SymbolTab, NULL, s);
8271
8272                   if(sym->reqv) {
8273                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8274                   } else {
8275                     strcat(bp1, sym->rname);
8276                   }
8277                   
8278                   while(*bp1)bp1++;
8279               }
8280               
8281               if(strlen(bp1) > cblen - 16) {
8282                 int i = strlen(cbuf);
8283                 cblen += 50;
8284                 cbuf = realloc(cbuf, cblen);
8285                 memset(cbuf+i, 0, 50);
8286                 bp1 = cbuf + i;
8287               }
8288             }
8289             
8290             free(buffer);
8291             buffer = Safe_strdup( cbuf );
8292             free(cbuf);
8293             
8294             bp = bp1 = buffer;
8295         }
8296
8297         /* emit each line as a code */
8298         while (*bp) {
8299                 if (*bp == '\n') {
8300                         *bp++ = '\0';
8301
8302                         if(*bp1)
8303                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8304                         bp1 = bp;
8305                 } else {
8306                         if (*bp == ':') {
8307                                 bp++;
8308                                 *bp = '\0';
8309                                 bp++;
8310
8311                                 /* print label, use this special format with NULL directive
8312                                  * to denote that the argument should not be indented with tab */
8313                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8314                                 bp1 = bp;
8315                         } else
8316                                 bp++;
8317                 }
8318         }
8319
8320         if ((bp1 != bp) && *bp1)
8321                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8322
8323
8324     Safe_free(buffer);
8325
8326     _G.inLine -= (!options.asmpeep);
8327 }
8328
8329 /*-----------------------------------------------------------------*/
8330 /* genRRC - rotate right with carry                                */
8331 /*-----------------------------------------------------------------*/
8332 static void genRRC (iCode *ic)
8333 {
8334   operand *left , *result ;
8335   int size, offset = 0, same;
8336
8337   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8338
8339   /* rotate right with carry */
8340   left = IC_LEFT(ic);
8341   result=IC_RESULT(ic);
8342   pic16_aopOp (left,ic,FALSE);
8343   pic16_aopOp (result,ic,TRUE);
8344
8345   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8346
8347   same = pic16_sameRegs(AOP(result),AOP(left));
8348
8349   size = AOP_SIZE(result);    
8350
8351   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8352
8353   /* get the lsb and put it into the carry */
8354   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8355
8356   offset = 0 ;
8357
8358   while(size--) {
8359
8360     if(same) {
8361       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8362     } else {
8363       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8364       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8365     }
8366
8367     offset++;
8368   }
8369
8370   pic16_freeAsmop(left,NULL,ic,TRUE);
8371   pic16_freeAsmop(result,NULL,ic,TRUE);
8372 }
8373
8374 /*-----------------------------------------------------------------*/
8375 /* genRLC - generate code for rotate left with carry               */
8376 /*-----------------------------------------------------------------*/
8377 static void genRLC (iCode *ic)
8378 {    
8379   operand *left , *result ;
8380   int size, offset = 0;
8381   int same;
8382
8383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8384   /* rotate right with carry */
8385   left = IC_LEFT(ic);
8386   result=IC_RESULT(ic);
8387   pic16_aopOp (left,ic,FALSE);
8388   pic16_aopOp (result,ic,TRUE);
8389
8390   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8391
8392   same = pic16_sameRegs(AOP(result),AOP(left));
8393
8394   /* move it to the result */
8395   size = AOP_SIZE(result);    
8396
8397   /* get the msb and put it into the carry */
8398   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8399
8400   offset = 0 ;
8401
8402   while(size--) {
8403
8404     if(same) {
8405       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8406     } else {
8407       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8408       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8409     }
8410
8411     offset++;
8412   }
8413
8414
8415   pic16_freeAsmop(left,NULL,ic,TRUE);
8416   pic16_freeAsmop(result,NULL,ic,TRUE);
8417 }
8418
8419
8420 /* gpasm can get the highest order bit with HIGH/UPPER
8421  * so the following probably is not needed -- VR */
8422  
8423 /*-----------------------------------------------------------------*/
8424 /* genGetHbit - generates code get highest order bit               */
8425 /*-----------------------------------------------------------------*/
8426 static void genGetHbit (iCode *ic)
8427 {
8428     operand *left, *result;
8429     left = IC_LEFT(ic);
8430     result=IC_RESULT(ic);
8431     pic16_aopOp (left,ic,FALSE);
8432     pic16_aopOp (result,ic,FALSE);
8433
8434     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8435     /* get the highest order byte into a */
8436     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8437     if(AOP_TYPE(result) == AOP_CRY){
8438         pic16_emitcode("rlc","a");
8439         pic16_outBitC(result);
8440     }
8441     else{
8442         pic16_emitcode("rl","a");
8443         pic16_emitcode("anl","a,#0x01");
8444         pic16_outAcc(result);
8445     }
8446
8447
8448     pic16_freeAsmop(left,NULL,ic,TRUE);
8449     pic16_freeAsmop(result,NULL,ic,TRUE);
8450 }
8451
8452 #if 0
8453 /*-----------------------------------------------------------------*/
8454 /* AccRol - rotate left accumulator by known count                 */
8455 /*-----------------------------------------------------------------*/
8456 static void AccRol (int shCount)
8457 {
8458     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8459     shCount &= 0x0007;              // shCount : 0..7
8460     switch(shCount){
8461         case 0 :
8462             break;
8463         case 1 :
8464             pic16_emitcode("rl","a");
8465             break;
8466         case 2 :
8467             pic16_emitcode("rl","a");
8468             pic16_emitcode("rl","a");
8469             break;
8470         case 3 :
8471             pic16_emitcode("swap","a");
8472             pic16_emitcode("rr","a");
8473             break;
8474         case 4 :
8475             pic16_emitcode("swap","a");
8476             break;
8477         case 5 :
8478             pic16_emitcode("swap","a");
8479             pic16_emitcode("rl","a");
8480             break;
8481         case 6 :
8482             pic16_emitcode("rr","a");
8483             pic16_emitcode("rr","a");
8484             break;
8485         case 7 :
8486             pic16_emitcode("rr","a");
8487             break;
8488     }
8489 }
8490 #endif
8491
8492 /*-----------------------------------------------------------------*/
8493 /* AccLsh - left shift accumulator by known count                  */
8494 /*-----------------------------------------------------------------*/
8495 static void AccLsh (int shCount)
8496 {
8497         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8498         switch(shCount){
8499                 case 0 :
8500                         return;
8501                         break;
8502                 case 1 :
8503                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8504                         break;
8505                 case 2 :
8506                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8507                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508                         break;
8509                 case 3 :
8510                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8511                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512                         break;
8513                 case 4 :
8514                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8515                         break;
8516                 case 5 :
8517                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8518                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8519                         break;
8520                 case 6 :
8521                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523                         break;
8524                 case 7 :
8525                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8526                         break;
8527         }
8528
8529         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8530 }
8531
8532 /*-----------------------------------------------------------------*/
8533 /* AccRsh - right shift accumulator by known count                 */
8534 /*-----------------------------------------------------------------*/
8535 static void AccRsh (int shCount, int andmask)
8536 {
8537         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8538         switch(shCount){
8539                 case 0 :
8540                         return; break;
8541                 case 1 :
8542                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543                         break;
8544                 case 2 :
8545                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8546                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8547                         break;
8548                 case 3 :
8549                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8550                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551                         break;
8552                 case 4 :
8553                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554                         break;
8555                 case 5 :
8556                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558                         break;
8559                 case 6 :
8560                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563                 case 7 :
8564                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         break;
8566         }
8567         
8568         if(andmask)
8569                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8570         else
8571                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8572 }
8573
8574 #if 0
8575 /*-----------------------------------------------------------------*/
8576 /* AccSRsh - signed right shift accumulator by known count                 */
8577 /*-----------------------------------------------------------------*/
8578 static void AccSRsh (int shCount)
8579 {
8580     symbol *tlbl ;
8581     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8582     if(shCount != 0){
8583         if(shCount == 1){
8584             pic16_emitcode("mov","c,acc.7");
8585             pic16_emitcode("rrc","a");
8586         } else if(shCount == 2){
8587             pic16_emitcode("mov","c,acc.7");
8588             pic16_emitcode("rrc","a");
8589             pic16_emitcode("mov","c,acc.7");
8590             pic16_emitcode("rrc","a");
8591         } else {
8592             tlbl = newiTempLabel(NULL);
8593             /* rotate right accumulator */
8594             AccRol(8 - shCount);
8595             /* and kill the higher order bits */
8596             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8597             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8598             pic16_emitcode("orl","a,#0x%02x",
8599                      (unsigned char)~SRMask[shCount]);
8600             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8601         }
8602     }
8603 }
8604 #endif
8605
8606 /*-----------------------------------------------------------------*/
8607 /* shiftR1Left2Result - shift right one byte from left to result   */
8608 /*-----------------------------------------------------------------*/
8609 static void shiftR1Left2ResultSigned (operand *left, int offl,
8610                                 operand *result, int offr,
8611                                 int shCount)
8612 {
8613   int same;
8614
8615   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8616
8617   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8618
8619   switch(shCount) {
8620   case 1:
8621     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8622     if(same) 
8623       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8624     else {
8625       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8626       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8627     }
8628
8629     break;
8630   case 2:
8631
8632     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8633     if(same) 
8634       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8635     else {
8636       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8637       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8638     }
8639     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8640     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8641
8642     break;
8643
8644   case 3:
8645     if(same)
8646       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8647     else {
8648       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8649       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8650     }
8651
8652     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8653     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8654     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8655
8656     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8657     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8658
8659     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8660     break;
8661
8662   case 4:
8663     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8664     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8665     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8666     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8667     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8668     break;
8669   case 5:
8670     if(same) {
8671       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8672     } else {
8673       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8674       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8675     }
8676     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8677     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8678     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8679     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8680     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8681     break;
8682
8683   case 6:
8684     if(same) {
8685       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8686       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8687       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8688       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8689       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8690       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691     } else {
8692       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8693       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8694       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8695       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8696       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8697     }
8698     break;
8699
8700   case 7:
8701     if(same) {
8702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8703       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8706     } else {
8707       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8708       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8709       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8710     }
8711
8712   default:
8713     break;
8714   }
8715 }
8716
8717 /*-----------------------------------------------------------------*/
8718 /* shiftR1Left2Result - shift right one byte from left to result   */
8719 /*-----------------------------------------------------------------*/
8720 static void shiftR1Left2Result (operand *left, int offl,
8721                                 operand *result, int offr,
8722                                 int shCount, int sign)
8723 {
8724   int same;
8725
8726   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8727
8728   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8729
8730   /* Copy the msb into the carry if signed. */
8731   if(sign) {
8732     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8733     return;
8734   }
8735
8736
8737
8738   switch(shCount) {
8739   case 1:
8740     emitCLRC;
8741     if(same) 
8742       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8743     else {
8744       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8745       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8746     }
8747     break;
8748   case 2:
8749     emitCLRC;
8750     if(same) {
8751       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8752     } else {
8753       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8754       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8755     }
8756     emitCLRC;
8757     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8758
8759     break;
8760   case 3:
8761     if(same)
8762       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8763     else {
8764       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8765       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8766     }
8767
8768     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8769     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8770     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8771     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772     break;
8773       
8774   case 4:
8775     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8776     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8777     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778     break;
8779
8780   case 5:
8781     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8783     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8784     //emitCLRC;
8785     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8786
8787     break;
8788   case 6:
8789
8790     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8791     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8792     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8793     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8794     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8795     break;
8796
8797   case 7:
8798
8799     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8800     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8801     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8802
8803     break;
8804
8805   default:
8806     break;
8807   }
8808 }
8809
8810 /*-----------------------------------------------------------------*/
8811 /* shiftL1Left2Result - shift left one byte from left to result    */
8812 /*-----------------------------------------------------------------*/
8813 static void shiftL1Left2Result (operand *left, int offl,
8814                                 operand *result, int offr, int shCount)
8815 {
8816   int same;
8817
8818   //    char *l;
8819   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8820
8821   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8822   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8823     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8824     //    MOVA(l);
8825     /* shift left accumulator */
8826     //AccLsh(shCount); // don't comment out just yet...
8827   //    pic16_aopPut(AOP(result),"a",offr);
8828
8829   switch(shCount) {
8830   case 1:
8831     /* Shift left 1 bit position */
8832     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8833     if(same) {
8834       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8835     } else {
8836       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8837       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8838     }
8839     break;
8840   case 2:
8841     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8842     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8843     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8844     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8845     break;
8846   case 3:
8847     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8849     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8851     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8852     break;
8853   case 4:
8854     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8855     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8856     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8857     break;
8858   case 5:
8859     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8860     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8861     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8862     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8863     break;
8864   case 6:
8865     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8867     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8869     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8870     break;
8871   case 7:
8872     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8873     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8874     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8875     break;
8876
8877   default:
8878     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8879   }
8880
8881 }
8882
8883 /*-----------------------------------------------------------------*/
8884 /* movLeft2Result - move byte from left to result                  */
8885 /*-----------------------------------------------------------------*/
8886 static void movLeft2Result (operand *left, int offl,
8887                             operand *result, int offr)
8888 {
8889   char *l;
8890   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8891   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8892     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8893
8894     if (*l == '@' && (IS_AOP_PREG(result))) {
8895       pic16_emitcode("mov","a,%s",l);
8896       pic16_aopPut(AOP(result),"a",offr);
8897     } else {
8898       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8899       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8900     }
8901   }
8902 }
8903
8904 /*-----------------------------------------------------------------*/
8905 /* shiftL2Left2Result - shift left two bytes from left to result   */
8906 /*-----------------------------------------------------------------*/
8907 static void shiftL2Left2Result (operand *left, int offl,
8908                                 operand *result, int offr, int shCount)
8909 {
8910   int same = pic16_sameRegs(AOP(result), AOP(left));
8911   int i;
8912
8913   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8914
8915   if (same && (offl != offr)) { // shift bytes
8916     if (offr > offl) {
8917        for(i=1;i>-1;i--) {
8918          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8919          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8920        }
8921     } else { // just treat as different later on
8922                 same = 0;
8923     }
8924   }
8925
8926   if(same) {
8927     switch(shCount) {
8928     case 0:
8929       break;
8930     case 1:
8931     case 2:
8932     case 3:
8933
8934       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8935       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8936       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8937
8938       while(--shCount) {
8939                 emitCLRC;
8940                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8941                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8942       }
8943
8944       break;
8945     case 4:
8946     case 5:
8947       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8948       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8949       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8950       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8952       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8953       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8954       if(shCount >=5) {
8955                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8956                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957       }
8958       break;
8959     case 6:
8960       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8961       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8962       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8963       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8964       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8965       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8966       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8969       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8970       break;
8971     case 7:
8972       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8973       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8975       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8976       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8977     }
8978
8979   } else {
8980     switch(shCount) {
8981     case 0:
8982       break;
8983     case 1:
8984     case 2:
8985     case 3:
8986       /* note, use a mov/add for the shift since the mov has a
8987          chance of getting optimized out */
8988       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8989       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8990       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8991       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8992       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8993
8994       while(--shCount) {
8995                 emitCLRC;
8996                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8997                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8998       }
8999       break;
9000
9001     case 4:
9002     case 5:
9003       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9004       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9005       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9006       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9007       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9008       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9009       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9010       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9011
9012
9013       if(shCount == 5) {
9014                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9015                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9016       }
9017       break;
9018     case 6:
9019       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9020       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9021       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9022       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9023
9024       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9026       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9028       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9030       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9031       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9032       break;
9033     case 7:
9034       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9035       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9036       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9037       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9038       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9039     }
9040   }
9041
9042 }
9043 /*-----------------------------------------------------------------*/
9044 /* shiftR2Left2Result - shift right two bytes from left to result  */
9045 /*-----------------------------------------------------------------*/
9046 static void shiftR2Left2Result (operand *left, int offl,
9047                                 operand *result, int offr,
9048                                 int shCount, int sign)
9049 {
9050   int same = pic16_sameRegs(AOP(result), AOP(left));
9051   int i;
9052   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9053
9054   if (same && (offl != offr)) { // shift right bytes
9055     if (offr < offl) {
9056        for(i=0;i<2;i++) {
9057          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9058          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9059        }
9060     } else { // just treat as different later on
9061                 same = 0;
9062     }
9063   }
9064
9065   switch(shCount) {
9066   case 0:
9067     break;
9068   case 1:
9069   case 2:
9070   case 3:
9071     if(sign)
9072       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9073     else
9074       emitCLRC;
9075
9076     if(same) {
9077       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9078       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9079     } else {
9080       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9081       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9082       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9083       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9084     }
9085
9086     while(--shCount) {
9087       if(sign)
9088                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9089       else
9090                 emitCLRC;
9091       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9092       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9093     }
9094     break;
9095   case 4:
9096   case 5:
9097     if(same) {
9098
9099       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9100       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9101       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9102
9103       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9104       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9105       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9106       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9107     } else {
9108       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9109       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9110       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9111
9112       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9113       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9114       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9115       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9116       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9117     }
9118
9119     if(shCount >=5) {
9120       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9121       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9122     }
9123
9124     if(sign) {
9125       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9126       pic16_emitpcode(POC_BTFSC, 
9127                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9128       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9129     }
9130
9131     break;
9132
9133   case 6:
9134     if(same) {
9135
9136       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9137       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9138
9139       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9140       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9141       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9142       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9143       if(sign) {
9144         pic16_emitpcode(POC_BTFSC, 
9145                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9146         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9147       }
9148       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9149       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9150       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9151       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9152     } else {
9153       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9154       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9156       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9157       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9158       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9159       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9160       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9161       if(sign) {
9162         pic16_emitpcode(POC_BTFSC, 
9163                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9164         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9165       }
9166       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9167       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9168
9169         
9170     }
9171
9172     break;
9173   case 7:
9174     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9175     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9176     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9177     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9178     if(sign) {
9179       emitSKPNC;
9180       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9181     } else 
9182       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9183   }
9184 }
9185
9186
9187 /*-----------------------------------------------------------------*/
9188 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9189 /*-----------------------------------------------------------------*/
9190 static void shiftLLeftOrResult (operand *left, int offl,
9191                                 operand *result, int offr, int shCount)
9192 {
9193     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9194
9195     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9196     /* shift left accumulator */
9197     AccLsh(shCount);
9198     /* or with result */
9199     /* back to result */
9200     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9201 }
9202
9203 /*-----------------------------------------------------------------*/
9204 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9205 /*-----------------------------------------------------------------*/
9206 static void shiftRLeftOrResult (operand *left, int offl,
9207                                 operand *result, int offr, int shCount)
9208 {
9209     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9210     
9211     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9212     /* shift right accumulator */
9213     AccRsh(shCount, 1);
9214     /* or with result */
9215     /* back to result */
9216     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9217 }
9218
9219 /*-----------------------------------------------------------------*/
9220 /* genlshOne - left shift a one byte quantity by known count       */
9221 /*-----------------------------------------------------------------*/
9222 static void genlshOne (operand *result, operand *left, int shCount)
9223 {       
9224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9225     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9226 }
9227
9228 /*-----------------------------------------------------------------*/
9229 /* genlshTwo - left shift two bytes by known amount != 0           */
9230 /*-----------------------------------------------------------------*/
9231 static void genlshTwo (operand *result,operand *left, int shCount)
9232 {
9233     int size;
9234     
9235     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9236     size = pic16_getDataSize(result);
9237
9238     /* if shCount >= 8 */
9239     if (shCount >= 8) {
9240         shCount -= 8 ;
9241
9242         if (size > 1){
9243             if (shCount)
9244                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9245             else 
9246                 movLeft2Result(left, LSB, result, MSB16);
9247         }
9248         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9249     }
9250
9251     /*  1 <= shCount <= 7 */
9252     else {  
9253         if(size == 1)
9254             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9255         else 
9256             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9257     }
9258 }
9259
9260 /*-----------------------------------------------------------------*/
9261 /* shiftLLong - shift left one long from left to result            */
9262 /* offr = LSB or MSB16                                             */
9263 /*-----------------------------------------------------------------*/
9264 static void shiftLLong (operand *left, operand *result, int offr )
9265 {
9266     int size = AOP_SIZE(result);
9267     int same = pic16_sameRegs(AOP(left),AOP(result));
9268         int i;
9269
9270     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9271
9272         if (same && (offr == MSB16)) { //shift one byte
9273                 for(i=size-1;i>=MSB16;i--) {
9274                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9275                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9276                 }
9277         } else {
9278                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9279         }
9280         
9281     if (size > LSB+offr ){
9282                 if (same) {
9283                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9284                 } else {
9285                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9286                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9287                 }
9288          }
9289
9290     if(size > MSB16+offr){
9291                 if (same) {
9292                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9293                 } else {
9294                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9295                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9296                 }
9297     }
9298
9299     if(size > MSB24+offr){
9300                 if (same) {
9301                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9302                 } else {
9303                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9304                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9305                 }
9306     }
9307
9308     if(size > MSB32+offr){
9309                 if (same) {
9310                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9311                 } else {
9312                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9313                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9314                 }
9315     }
9316     if(offr != LSB)
9317                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9318
9319 }
9320
9321 /*-----------------------------------------------------------------*/
9322 /* genlshFour - shift four byte by a known amount != 0             */
9323 /*-----------------------------------------------------------------*/
9324 static void genlshFour (operand *result, operand *left, int shCount)
9325 {
9326     int size;
9327
9328     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9329     size = AOP_SIZE(result);
9330
9331     /* if shifting more that 3 bytes */
9332     if (shCount >= 24 ) {
9333         shCount -= 24;
9334         if (shCount)
9335             /* lowest order of left goes to the highest
9336             order of the destination */
9337             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9338         else
9339             movLeft2Result(left, LSB, result, MSB32);
9340
9341                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9342                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9343                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9344
9345         return;
9346     }
9347
9348     /* more than two bytes */
9349     else if ( shCount >= 16 ) {
9350         /* lower order two bytes goes to higher order two bytes */
9351         shCount -= 16;
9352         /* if some more remaining */
9353         if (shCount)
9354             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9355         else {
9356             movLeft2Result(left, MSB16, result, MSB32);
9357             movLeft2Result(left, LSB, result, MSB24);
9358         }
9359                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9360                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9361         return;
9362     }    
9363
9364     /* if more than 1 byte */
9365     else if ( shCount >= 8 ) {
9366         /* lower order three bytes goes to higher order  three bytes */
9367         shCount -= 8;
9368         if(size == 2){
9369             if(shCount)
9370                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9371             else
9372                 movLeft2Result(left, LSB, result, MSB16);
9373         }
9374         else{   /* size = 4 */
9375             if(shCount == 0){
9376                 movLeft2Result(left, MSB24, result, MSB32);
9377                 movLeft2Result(left, MSB16, result, MSB24);
9378                 movLeft2Result(left, LSB, result, MSB16);
9379                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9380             }
9381             else if(shCount == 1)
9382                 shiftLLong(left, result, MSB16);
9383             else{
9384                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9385                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9386                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9387                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9388             }
9389         }
9390     }
9391
9392     /* 1 <= shCount <= 7 */
9393     else if(shCount <= 3)
9394     { 
9395         shiftLLong(left, result, LSB);
9396         while(--shCount >= 1)
9397             shiftLLong(result, result, LSB);
9398     }
9399     /* 3 <= shCount <= 7, optimize */
9400     else{
9401         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9402         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9403         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9404     }
9405 }
9406
9407 /*-----------------------------------------------------------------*/
9408 /* genLeftShiftLiteral - left shifting by known count              */
9409 /*-----------------------------------------------------------------*/
9410 void pic16_genLeftShiftLiteral (operand *left,
9411                                  operand *right,
9412                                  operand *result,
9413                                  iCode *ic)
9414 {    
9415     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9416     int size;
9417
9418     FENTRY;
9419     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9420     pic16_freeAsmop(right,NULL,ic,TRUE);
9421
9422     pic16_aopOp(left,ic,FALSE);
9423     pic16_aopOp(result,ic,TRUE);
9424
9425     size = getSize(operandType(result));
9426
9427 #if VIEW_SIZE
9428     pic16_emitcode("; shift left ","result %d, left %d",size,
9429              AOP_SIZE(left));
9430 #endif
9431
9432     /* I suppose that the left size >= result size */
9433     if(shCount == 0){
9434         while(size--){
9435             movLeft2Result(left, size, result, size);
9436         }
9437     }
9438
9439     else if(shCount >= (size * 8))
9440         while(size--)
9441             pic16_aopPut(AOP(result),zero,size);
9442     else{
9443         switch (size) {
9444             case 1:
9445                 genlshOne (result,left,shCount);
9446                 break;
9447
9448             case 2:
9449             case 3:
9450                 genlshTwo (result,left,shCount);
9451                 break;
9452
9453             case 4:
9454                 genlshFour (result,left,shCount);
9455                 break;
9456         }
9457     }
9458     pic16_freeAsmop(left,NULL,ic,TRUE);
9459     pic16_freeAsmop(result,NULL,ic,TRUE);
9460 }
9461
9462 /*-----------------------------------------------------------------*
9463  * genMultiAsm - repeat assembly instruction for size of register.
9464  * if endian == 1, then the high byte (i.e base address + size of 
9465  * register) is used first else the low byte is used first;
9466  *-----------------------------------------------------------------*/
9467 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9468 {
9469
9470   int offset = 0;
9471
9472   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9473
9474   if(!reg)
9475     return;
9476
9477   if(!endian) {
9478     endian = 1;
9479   } else {
9480     endian = -1;
9481     offset = size-1;
9482   }
9483
9484   while(size--) {
9485     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9486     offset += endian;
9487   }
9488
9489 }
9490
9491 #if !(USE_GENERIC_SIGNED_SHIFT)
9492 /*-----------------------------------------------------------------*/
9493 /* genLeftShift - generates code for left shifting                 */
9494 /*-----------------------------------------------------------------*/
9495 static void genLeftShift (iCode *ic)
9496 {
9497   operand *left,*right, *result;
9498   int size, offset;
9499 //  char *l;
9500   symbol *tlbl , *tlbl1;
9501   pCodeOp *pctemp;
9502
9503   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9504
9505   right = IC_RIGHT(ic);
9506   left  = IC_LEFT(ic);
9507   result = IC_RESULT(ic);
9508
9509   pic16_aopOp(right,ic,FALSE);
9510
9511   /* if the shift count is known then do it 
9512      as efficiently as possible */
9513   if (AOP_TYPE(right) == AOP_LIT) {
9514     pic16_genLeftShiftLiteral (left,right,result,ic);
9515     return ;
9516   }
9517
9518   /* shift count is unknown then we have to form
9519    * a loop. Get the loop count in WREG : Note: we take
9520    * only the lower order byte since shifting
9521    * more than 32 bits make no sense anyway, ( the
9522    * largest size of an object can be only 32 bits ) */
9523   
9524   pic16_aopOp(left,ic,FALSE);
9525   pic16_aopOp(result,ic,FALSE);
9526
9527   /* now move the left to the result if they are not the
9528    * same, and if size > 1,
9529    * and if right is not same to result (!!!) -- VR */
9530   if (!pic16_sameRegs(AOP(left),AOP(result))
9531       && (AOP_SIZE(result) > 1)) {
9532
9533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9534
9535     size = AOP_SIZE(result);
9536     offset=0;
9537     while (size--) {
9538
9539 #if 0
9540       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9541       if (*l == '@' && (IS_AOP_PREG(result))) {
9542
9543           pic16_emitcode("mov","a,%s",l);
9544           pic16_aopPut(AOP(result),"a",offset);
9545       } else
9546 #endif
9547       {
9548         /* we don't know if left is a literal or a register, take care -- VR */
9549         mov2f(AOP(result), AOP(left), offset);
9550       }
9551       offset++;
9552     }
9553   }
9554
9555   size = AOP_SIZE(result);
9556
9557   /* if it is only one byte then */
9558   if (size == 1) {
9559     if(optimized_for_speed) {
9560       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9561       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9562       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9563       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9564       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9565       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9566       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9567       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9568       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9569       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9570       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9571       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9572     } else {
9573
9574       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9575
9576       tlbl = newiTempLabel(NULL);
9577
9578 #if 1
9579       /* this is already done, why change it? */
9580       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9581                 mov2f(AOP(result), AOP(left), 0);
9582       }
9583 #endif
9584
9585       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9586       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9587       pic16_emitpLabel(tlbl->key);
9588       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9589       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9590       emitSKPC;
9591       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9592     }
9593     goto release ;
9594   }
9595     
9596   if (pic16_sameRegs(AOP(left),AOP(result))) {
9597
9598     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9599     
9600     tlbl = newiTempLabel(NULL);
9601     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9602     genMultiAsm(POC_RRCF, result, size,1);
9603     pic16_emitpLabel(tlbl->key);
9604     genMultiAsm(POC_RLCF, result, size,0);
9605     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9606     emitSKPC;
9607     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9608     goto release;
9609   }
9610
9611   //tlbl = newiTempLabel(NULL);
9612   //offset = 0 ;   
9613   //tlbl1 = newiTempLabel(NULL);
9614
9615   //reAdjustPreg(AOP(result));    
9616     
9617   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9618   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9619   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9620   //MOVA(l);
9621   //pic16_emitcode("add","a,acc");         
9622   //pic16_aopPut(AOP(result),"a",offset++);
9623   //while (--size) {
9624   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9625   //  MOVA(l);
9626   //  pic16_emitcode("rlc","a");         
9627   //  pic16_aopPut(AOP(result),"a",offset++);
9628   //}
9629   //reAdjustPreg(AOP(result));
9630
9631   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9632   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9633
9634
9635   tlbl = newiTempLabel(NULL);
9636   tlbl1= newiTempLabel(NULL);
9637
9638   size = AOP_SIZE(result);
9639   offset = 1;
9640
9641   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9642
9643   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9644
9645   /* offset should be 0, 1 or 3 */
9646   
9647   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9648   emitSKPNZ;
9649   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9650
9651   pic16_emitpcode(POC_MOVWF, pctemp);
9652
9653
9654   pic16_emitpLabel(tlbl->key);
9655
9656   emitCLRC;
9657   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9658   while(--size)
9659     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9660
9661   pic16_emitpcode(POC_DECFSZ,  pctemp);
9662   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9663   pic16_emitpLabel(tlbl1->key);
9664
9665   pic16_popReleaseTempReg(pctemp,1);
9666
9667
9668  release:
9669   pic16_freeAsmop (right,NULL,ic,TRUE);
9670   pic16_freeAsmop(left,NULL,ic,TRUE);
9671   pic16_freeAsmop(result,NULL,ic,TRUE);
9672 }
9673 #endif
9674
9675
9676 #if 0
9677 #error old code (left here for reference)
9678 /*-----------------------------------------------------------------*/
9679 /* genLeftShift - generates code for left shifting                 */
9680 /*-----------------------------------------------------------------*/
9681 static void genLeftShift (iCode *ic)
9682 {
9683   operand *left,*right, *result;
9684   int size, offset;
9685   char *l;
9686   symbol *tlbl , *tlbl1;
9687   pCodeOp *pctemp;
9688
9689   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9690
9691   right = IC_RIGHT(ic);
9692   left  = IC_LEFT(ic);
9693   result = IC_RESULT(ic);
9694
9695   pic16_aopOp(right,ic,FALSE);
9696
9697   /* if the shift count is known then do it 
9698      as efficiently as possible */
9699   if (AOP_TYPE(right) == AOP_LIT) {
9700     pic16_genLeftShiftLiteral (left,right,result,ic);
9701     return ;
9702   }
9703
9704   /* shift count is unknown then we have to form 
9705      a loop get the loop count in B : Note: we take
9706      only the lower order byte since shifting
9707      more that 32 bits make no sense anyway, ( the
9708      largest size of an object can be only 32 bits ) */  
9709
9710     
9711   pic16_aopOp(left,ic,FALSE);
9712   pic16_aopOp(result,ic,FALSE);
9713
9714   /* now move the left to the result if they are not the
9715      same */
9716   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9717       AOP_SIZE(result) > 1) {
9718
9719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9720
9721     size = AOP_SIZE(result);
9722     offset=0;
9723     while (size--) {
9724       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9725       if (*l == '@' && (IS_AOP_PREG(result))) {
9726
9727         pic16_emitcode("mov","a,%s",l);
9728         pic16_aopPut(AOP(result),"a",offset);
9729       } else {
9730
9731         /* we don't know if left is a literal or a register, take care -- VR */
9732         mov2f(AOP(result), AOP(left), offset);
9733       }
9734       offset++;
9735     }
9736   }
9737
9738   size = AOP_SIZE(result);
9739
9740   /* if it is only one byte then */
9741   if (size == 1) {
9742     if(optimized_for_speed) {
9743       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9744       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9745       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9746       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9747       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9748       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9749       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9750       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9751       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9752       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9753       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9754       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9755     } else {
9756
9757       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9758
9759       tlbl = newiTempLabel(NULL);
9760       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9761                 mov2f(AOP(result), AOP(left), 0);
9762                 
9763 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9764 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9765       }
9766
9767       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9768       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9769       pic16_emitpLabel(tlbl->key);
9770       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9771       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9772       emitSKPC;
9773       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9774     }
9775     goto release ;
9776   }
9777     
9778   if (pic16_sameRegs(AOP(left),AOP(result))) {
9779
9780     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9781     
9782     tlbl = newiTempLabel(NULL);
9783     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9784     genMultiAsm(POC_RRCF, result, size,1);
9785     pic16_emitpLabel(tlbl->key);
9786     genMultiAsm(POC_RLCF, result, size,0);
9787     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9788     emitSKPC;
9789     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9790     goto release;
9791   }
9792
9793   //tlbl = newiTempLabel(NULL);
9794   //offset = 0 ;   
9795   //tlbl1 = newiTempLabel(NULL);
9796
9797   //reAdjustPreg(AOP(result));    
9798     
9799   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9800   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9801   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9802   //MOVA(l);
9803   //pic16_emitcode("add","a,acc");         
9804   //pic16_aopPut(AOP(result),"a",offset++);
9805   //while (--size) {
9806   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9807   //  MOVA(l);
9808   //  pic16_emitcode("rlc","a");         
9809   //  pic16_aopPut(AOP(result),"a",offset++);
9810   //}
9811   //reAdjustPreg(AOP(result));
9812
9813   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9814   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9815
9816
9817   tlbl = newiTempLabel(NULL);
9818   tlbl1= newiTempLabel(NULL);
9819
9820   size = AOP_SIZE(result);
9821   offset = 1;
9822
9823   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9824
9825   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9826
9827   /* offset should be 0, 1 or 3 */
9828   
9829   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9830   emitSKPNZ;
9831   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9832
9833   pic16_emitpcode(POC_MOVWF, pctemp);
9834
9835
9836   pic16_emitpLabel(tlbl->key);
9837
9838   emitCLRC;
9839   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9840   while(--size)
9841     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9842
9843   pic16_emitpcode(POC_DECFSZ,  pctemp);
9844   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9845   pic16_emitpLabel(tlbl1->key);
9846
9847   pic16_popReleaseTempReg(pctemp,1);
9848
9849
9850  release:
9851   pic16_freeAsmop (right,NULL,ic,TRUE);
9852   pic16_freeAsmop(left,NULL,ic,TRUE);
9853   pic16_freeAsmop(result,NULL,ic,TRUE);
9854 }
9855 #endif
9856
9857 /*-----------------------------------------------------------------*/
9858 /* genrshOne - right shift a one byte quantity by known count      */
9859 /*-----------------------------------------------------------------*/
9860 static void genrshOne (operand *result, operand *left,
9861                        int shCount, int sign)
9862 {
9863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9864     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9865 }
9866
9867 /*-----------------------------------------------------------------*/
9868 /* genrshTwo - right shift two bytes by known amount != 0          */
9869 /*-----------------------------------------------------------------*/
9870 static void genrshTwo (operand *result,operand *left,
9871                        int shCount, int sign)
9872 {
9873   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9874   /* if shCount >= 8 */
9875   if (shCount >= 8) {
9876     shCount -= 8 ;
9877     if (shCount)
9878       shiftR1Left2Result(left, MSB16, result, LSB,
9879                          shCount, sign);
9880     else
9881       movLeft2Result(left, MSB16, result, LSB);
9882
9883     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9884
9885     if(sign) {
9886       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9887       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9888     }
9889   }
9890
9891   /*  1 <= shCount <= 7 */
9892   else
9893     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9894 }
9895
9896 /*-----------------------------------------------------------------*/
9897 /* shiftRLong - shift right one long from left to result           */
9898 /* offl = LSB or MSB16                                             */
9899 /*-----------------------------------------------------------------*/
9900 static void shiftRLong (operand *left, int offl,
9901                         operand *result, int sign)
9902 {
9903     int size = AOP_SIZE(result);
9904     int same = pic16_sameRegs(AOP(left),AOP(result));
9905     int i;
9906     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9907
9908         if (same && (offl == MSB16)) { //shift one byte right
9909                 for(i=MSB16;i<size;i++) {
9910                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9911                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9912                 }
9913         }
9914
9915     if(sign)
9916                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9917         else
9918                 emitCLRC;
9919
9920         if (same) {
9921                 if (offl == LSB)
9922                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9923         } else {
9924         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9925         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9926         }
9927
9928     if(offl == MSB16) {
9929         /* add sign of "a" */
9930         pic16_addSign(result, MSB32, sign);
9931         }
9932
9933         if (same) {
9934         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9935         } else {
9936         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9937         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9938         }
9939         
9940         if (same) {
9941         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9942         } else {
9943         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9944         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9945         }
9946
9947         if (same) {
9948         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9949         } else {
9950         if(offl == LSB){
9951                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9952                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9953         }
9954         }
9955 }
9956
9957 /*-----------------------------------------------------------------*/
9958 /* genrshFour - shift four byte by a known amount != 0             */
9959 /*-----------------------------------------------------------------*/
9960 static void genrshFour (operand *result, operand *left,
9961                         int shCount, int sign)
9962 {
9963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9964   /* if shifting more that 3 bytes */
9965   if(shCount >= 24 ) {
9966     shCount -= 24;
9967     if(shCount)
9968       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9969     else
9970       movLeft2Result(left, MSB32, result, LSB);
9971
9972     pic16_addSign(result, MSB16, sign);
9973   }
9974   else if(shCount >= 16){
9975     shCount -= 16;
9976     if(shCount)
9977       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9978     else{
9979       movLeft2Result(left, MSB24, result, LSB);
9980       movLeft2Result(left, MSB32, result, MSB16);
9981     }
9982     pic16_addSign(result, MSB24, sign);
9983   }
9984   else if(shCount >= 8){
9985     shCount -= 8;
9986     if(shCount == 1)
9987       shiftRLong(left, MSB16, result, sign);
9988     else if(shCount == 0){
9989       movLeft2Result(left, MSB16, result, LSB);
9990       movLeft2Result(left, MSB24, result, MSB16);
9991       movLeft2Result(left, MSB32, result, MSB24);
9992       pic16_addSign(result, MSB32, sign);
9993     }
9994     else{ //shcount >= 2
9995       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9996       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9997       /* the last shift is signed */
9998       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9999       pic16_addSign(result, MSB32, sign);
10000     }
10001   }
10002   else{   /* 1 <= shCount <= 7 */
10003     if(shCount <= 2){
10004       shiftRLong(left, LSB, result, sign);
10005       if(shCount == 2)
10006         shiftRLong(result, LSB, result, sign);
10007     }
10008     else{
10009       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10010       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10011       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10012     }
10013   }
10014 }
10015
10016 /*-----------------------------------------------------------------*/
10017 /* genRightShiftLiteral - right shifting by known count            */
10018 /*-----------------------------------------------------------------*/
10019 static void genRightShiftLiteral (operand *left,
10020                                   operand *right,
10021                                   operand *result,
10022                                   iCode *ic,
10023                                   int sign)
10024 {    
10025   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10026   int lsize,res_size;
10027
10028   pic16_freeAsmop(right,NULL,ic,TRUE);
10029
10030   pic16_aopOp(left,ic,FALSE);
10031   pic16_aopOp(result,ic,TRUE);
10032
10033   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10034
10035 #if VIEW_SIZE
10036   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10037                  AOP_SIZE(left));
10038 #endif
10039
10040   lsize = pic16_getDataSize(left);
10041   res_size = pic16_getDataSize(result);
10042   /* test the LEFT size !!! */
10043
10044   /* I suppose that the left size >= result size */
10045   if(shCount == 0){
10046     assert (res_size <= lsize);
10047     while (res_size--) {
10048       mov2f (AOP(result), AOP(left), res_size);
10049     } // for
10050   }
10051
10052   else if(shCount >= (lsize * 8)){
10053
10054     if(res_size == 1) {
10055       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10056       if(sign) {
10057         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10058         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10059       }
10060     } else {
10061
10062       if(sign) {
10063         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10064         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10065         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10066         while(res_size--)
10067           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10068
10069       } else {
10070
10071         while(res_size--)
10072           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10073       }
10074     }
10075   } else {
10076
10077     switch (res_size) {
10078     case 1:
10079       genrshOne (result,left,shCount,sign);
10080       break;
10081
10082     case 2:
10083       genrshTwo (result,left,shCount,sign);
10084       break;
10085
10086     case 4:
10087       genrshFour (result,left,shCount,sign);
10088       break;
10089     default :
10090       break;
10091     }
10092
10093   }
10094
10095   pic16_freeAsmop(left,NULL,ic,TRUE);
10096   pic16_freeAsmop(result,NULL,ic,TRUE);
10097 }
10098
10099 #if !(USE_GENERIC_SIGNED_SHIFT)
10100 /*-----------------------------------------------------------------*/
10101 /* genSignedRightShift - right shift of signed number              */
10102 /*-----------------------------------------------------------------*/
10103 static void genSignedRightShift (iCode *ic)
10104 {
10105   operand *right, *left, *result;
10106   int size, offset;
10107   //  char *l;
10108   symbol *tlbl, *tlbl1 ;
10109   pCodeOp *pctemp;
10110
10111   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10112
10113   /* we do it the hard way put the shift count in b
10114      and loop thru preserving the sign */
10115   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10116
10117   right = IC_RIGHT(ic);
10118   left  = IC_LEFT(ic);
10119   result = IC_RESULT(ic);
10120
10121   pic16_aopOp(right,ic,FALSE);  
10122   pic16_aopOp(left,ic,FALSE);
10123   pic16_aopOp(result,ic,FALSE);
10124
10125
10126   if ( AOP_TYPE(right) == AOP_LIT) {
10127     genRightShiftLiteral (left,right,result,ic,1);
10128     return ;
10129   }
10130   /* shift count is unknown then we have to form 
10131      a loop get the loop count in B : Note: we take
10132      only the lower order byte since shifting
10133      more that 32 bits make no sense anyway, ( the
10134      largest size of an object can be only 32 bits ) */  
10135
10136   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10137   //pic16_emitcode("inc","b");
10138   //pic16_freeAsmop (right,NULL,ic,TRUE);
10139   //pic16_aopOp(left,ic,FALSE);
10140   //pic16_aopOp(result,ic,FALSE);
10141
10142   /* now move the left to the result if they are not the
10143      same */
10144   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10145       AOP_SIZE(result) > 1) {
10146
10147     size = AOP_SIZE(result);
10148     offset=0;
10149     while (size--) { 
10150       /*
10151         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10152         if (*l == '@' && IS_AOP_PREG(result)) {
10153
10154         pic16_emitcode("mov","a,%s",l);
10155         pic16_aopPut(AOP(result),"a",offset);
10156         } else
10157         pic16_aopPut(AOP(result),l,offset);
10158       */
10159       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10160       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10161
10162       offset++;
10163     }
10164   }
10165
10166   /* mov the highest order bit to OVR */    
10167   tlbl = newiTempLabel(NULL);
10168   tlbl1= newiTempLabel(NULL);
10169
10170   size = AOP_SIZE(result);
10171   offset = size - 1;
10172
10173   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10174
10175   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10176
10177   /* offset should be 0, 1 or 3 */
10178   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10179   emitSKPNZ;
10180   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10181
10182   pic16_emitpcode(POC_MOVWF, pctemp);
10183
10184
10185   pic16_emitpLabel(tlbl->key);
10186
10187   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10188   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10189
10190   while(--size) {
10191     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10192   }
10193
10194   pic16_emitpcode(POC_DECFSZ,  pctemp);
10195   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10196   pic16_emitpLabel(tlbl1->key);
10197
10198   pic16_popReleaseTempReg(pctemp,1);
10199 #if 0
10200   size = AOP_SIZE(result);
10201   offset = size - 1;
10202   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10203   pic16_emitcode("rlc","a");
10204   pic16_emitcode("mov","ov,c");
10205   /* if it is only one byte then */
10206   if (size == 1) {
10207     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10208     MOVA(l);
10209     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10210     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10211     pic16_emitcode("mov","c,ov");
10212     pic16_emitcode("rrc","a");
10213     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10214     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10215     pic16_aopPut(AOP(result),"a",0);
10216     goto release ;
10217   }
10218
10219   reAdjustPreg(AOP(result));
10220   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10221   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10222   pic16_emitcode("mov","c,ov");
10223   while (size--) {
10224     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10225     MOVA(l);
10226     pic16_emitcode("rrc","a");         
10227     pic16_aopPut(AOP(result),"a",offset--);
10228   }
10229   reAdjustPreg(AOP(result));
10230   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10231   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10232
10233  release:
10234 #endif
10235
10236   pic16_freeAsmop(left,NULL,ic,TRUE);
10237   pic16_freeAsmop(result,NULL,ic,TRUE);
10238   pic16_freeAsmop(right,NULL,ic,TRUE);
10239 }
10240 #endif
10241
10242 #if !(USE_GENERIC_SIGNED_SHIFT)
10243 #warning This implementation of genRightShift() is incomplete!
10244 /*-----------------------------------------------------------------*/
10245 /* genRightShift - generate code for right shifting                */
10246 /*-----------------------------------------------------------------*/
10247 static void genRightShift (iCode *ic)
10248 {
10249     operand *right, *left, *result;
10250     sym_link *letype ;
10251     int size, offset;
10252     char *l;
10253     symbol *tlbl, *tlbl1 ;
10254
10255     /* if signed then we do it the hard way preserve the
10256     sign bit moving it inwards */
10257     letype = getSpec(operandType(IC_LEFT(ic)));
10258     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10259
10260     if (!SPEC_USIGN(letype)) {
10261         genSignedRightShift (ic);
10262         return ;
10263     }
10264
10265     /* signed & unsigned types are treated the same : i.e. the
10266     signed is NOT propagated inwards : quoting from the
10267     ANSI - standard : "for E1 >> E2, is equivalent to division
10268     by 2**E2 if unsigned or if it has a non-negative value,
10269     otherwise the result is implementation defined ", MY definition
10270     is that the sign does not get propagated */
10271
10272     right = IC_RIGHT(ic);
10273     left  = IC_LEFT(ic);
10274     result = IC_RESULT(ic);
10275
10276     pic16_aopOp(right,ic,FALSE);
10277
10278     /* if the shift count is known then do it 
10279     as efficiently as possible */
10280     if (AOP_TYPE(right) == AOP_LIT) {
10281         genRightShiftLiteral (left,right,result,ic, 0);
10282         return ;
10283     }
10284
10285     /* shift count is unknown then we have to form 
10286     a loop get the loop count in B : Note: we take
10287     only the lower order byte since shifting
10288     more that 32 bits make no sense anyway, ( the
10289     largest size of an object can be only 32 bits ) */  
10290
10291     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10292     pic16_emitcode("inc","b");
10293     pic16_aopOp(left,ic,FALSE);
10294     pic16_aopOp(result,ic,FALSE);
10295
10296     /* now move the left to the result if they are not the
10297     same */
10298     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10299         AOP_SIZE(result) > 1) {
10300
10301         size = AOP_SIZE(result);
10302         offset=0;
10303         while (size--) {
10304             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10305             if (*l == '@' && IS_AOP_PREG(result)) {
10306
10307                 pic16_emitcode("mov","a,%s",l);
10308                 pic16_aopPut(AOP(result),"a",offset);
10309             } else
10310                 pic16_aopPut(AOP(result),l,offset);
10311             offset++;
10312         }
10313     }
10314
10315     tlbl = newiTempLabel(NULL);
10316     tlbl1= newiTempLabel(NULL);
10317     size = AOP_SIZE(result);
10318     offset = size - 1;
10319
10320     /* if it is only one byte then */
10321     if (size == 1) {
10322
10323       tlbl = newiTempLabel(NULL);
10324       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10325         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10326         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10327       }
10328
10329       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10330       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10331       pic16_emitpLabel(tlbl->key);
10332       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10333       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10334       emitSKPC;
10335       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10336
10337       goto release ;
10338     }
10339
10340     reAdjustPreg(AOP(result));
10341     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10342     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10343     CLRC;
10344     while (size--) {
10345         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10346         MOVA(l);
10347         pic16_emitcode("rrc","a");         
10348         pic16_aopPut(AOP(result),"a",offset--);
10349     }
10350     reAdjustPreg(AOP(result));
10351
10352     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10353     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10354
10355 release:
10356     pic16_freeAsmop(left,NULL,ic,TRUE);
10357     pic16_freeAsmop (right,NULL,ic,TRUE);
10358     pic16_freeAsmop(result,NULL,ic,TRUE);
10359 }
10360 #endif
10361
10362 #if (USE_GENERIC_SIGNED_SHIFT)
10363 /*-----------------------------------------------------------------*/
10364 /* genGenericShift - generates code for left or right shifting     */
10365 /*-----------------------------------------------------------------*/
10366 static void genGenericShift (iCode *ic, int isShiftLeft) {
10367   operand *left,*right, *result;
10368   int offset;
10369   int sign, signedCount;
10370   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10371   PIC_OPCODE pos_shift, neg_shift;
10372
10373   FENTRY;
10374
10375   right = IC_RIGHT(ic);
10376   left  = IC_LEFT(ic);
10377   result = IC_RESULT(ic);
10378
10379   pic16_aopOp(right,ic,FALSE);
10380   pic16_aopOp(left,ic,FALSE);
10381   pic16_aopOp(result,ic,TRUE);
10382
10383   sign = !SPEC_USIGN(operandType (left));
10384   signedCount = !SPEC_USIGN(operandType (right));
10385
10386   /* if the shift count is known then do it 
10387      as efficiently as possible */
10388   if (AOP_TYPE(right) == AOP_LIT) {
10389     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10390     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10391     // we should modify right->aopu.aop_lit here!
10392     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10393     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10394     if (isShiftLeft)
10395       pic16_genLeftShiftLiteral (left,right,result,ic);
10396     else
10397       genRightShiftLiteral (left,right,result,ic, sign);
10398
10399     goto release;
10400   } // if (right is literal)
10401
10402   /* shift count is unknown then we have to form a loop.
10403    * Note: we take only the lower order byte since shifting
10404    * more than 32 bits make no sense anyway, ( the
10405    * largest size of an object can be only 32 bits )
10406    * Note: we perform arithmetic shifts if the left operand is
10407    * signed and we do an (effective) right shift, i. e. we
10408    * shift in the sign bit from the left. */
10409    
10410   label_complete = newiTempLabel ( NULL );
10411   label_loop_pos = newiTempLabel ( NULL );
10412   label_loop_neg = NULL;
10413   label_negative = NULL;
10414   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10415   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10416
10417   if (signedCount) {
10418     // additional labels needed
10419     label_loop_neg = newiTempLabel ( NULL );
10420     label_negative = newiTempLabel ( NULL );
10421   } // if
10422
10423   // copy source to result -- this will effectively truncate the left operand to the size of result!
10424   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10425   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10426   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10427     mov2f (AOP(result),AOP(left), offset);
10428   } // for
10429
10430   // if result is longer than left, fill with zeros (or sign)
10431   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10432     if (sign && AOP_SIZE(left) > 0) {
10433       // shift signed operand -- fill with sign
10434       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10435       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10436       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10437       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10438         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10439       } // for
10440     } else {
10441       // shift unsigned operand -- fill result with zeros
10442       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10444       } // for
10445     }
10446   } // if (size mismatch)
10447
10448   pic16_mov2w (AOP(right), 0);
10449   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10450   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10451   
10452 #if 0
10453   // perform a shift by one (shift count is positive)
10454   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10455   // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3]          ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10456   pic16_emitpLabel (label_loop_pos->key);
10457   emitCLRC;
10458   if (sign && (pos_shift == POC_RRCF)) {
10459     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10460     emitSETC;
10461   } // if
10462   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10463   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10464   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10465 #else
10466   // perform a shift by one (shift count is positive)
10467   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10468   // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6]        ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10469   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10470   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10471   emitCLRC;
10472   pic16_emitpLabel (label_loop_pos->key);
10473   if (sign && (pos_shift == POC_RRCF)) {
10474     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10475     emitSETC;
10476   } // if
10477   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10478   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10479   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10480   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10481 #endif
10482
10483   if (signedCount) {
10484     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10485
10486     pic16_emitpLabel (label_negative->key);
10487     // perform a shift by -1 (shift count is negative)
10488     // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4                   ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10489     emitCLRC;
10490     pic16_emitpLabel (label_loop_neg->key);
10491     if (sign && (neg_shift == POC_RRCF)) {
10492       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10493       emitSETC;
10494     } // if
10495     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10496     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10497     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10498     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10499   } // if (signedCount)
10500
10501   pic16_emitpLabel (label_complete->key);
10502
10503 release:
10504   pic16_freeAsmop (right,NULL,ic,TRUE);
10505   pic16_freeAsmop(left,NULL,ic,TRUE);
10506   pic16_freeAsmop(result,NULL,ic,TRUE);
10507 }
10508
10509 static void genLeftShift (iCode *ic) {
10510   genGenericShift (ic, 1);
10511 }
10512
10513 static void genRightShift (iCode *ic) {
10514   genGenericShift (ic, 0);
10515 }
10516 #endif
10517
10518
10519 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10520 void pic16_loadFSR0(operand *op, int lit)
10521 {
10522   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10523     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10524   } else {
10525     assert (!OP_SYMBOL(op)->remat);
10526     // set up FSR0 with address of result
10527     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10528     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10529   }
10530 }
10531
10532 /*-----------------------------------------------------------------*/
10533 /* genUnpackBits - generates code for unpacking bits               */
10534 /*-----------------------------------------------------------------*/
10535 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10536 {    
10537   int shCnt ;
10538   int rlen = 0 ;
10539   sym_link *etype, *letype;
10540   int blen=0, bstr=0;
10541   int lbstr;
10542   int offset = 0 ;
10543
10544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10545     etype = getSpec(operandType(result));
10546     letype = getSpec(operandType(left));
10547     
10548 //    if(IS_BITFIELD(etype)) {
10549       blen = SPEC_BLEN(etype);
10550       bstr = SPEC_BSTR(etype);
10551 //    }
10552
10553     lbstr = SPEC_BSTR( letype );
10554
10555 #if 1
10556     if((blen == 1) && (bstr < 8)) {
10557       /* it is a single bit, so use the appropriate bit instructions */
10558       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10559
10560       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10561       
10562       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10563       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10564         /* workaround to reduce the extra lfsr instruction */
10565         pic16_emitpcode(POC_BTFSC,
10566               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10567       } else {
10568         pic16_loadFSR0 (left, 0);
10569         pic16_emitpcode(POC_BTFSC,
10570               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10571       }
10572         
10573       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10574
10575       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10576       return;
10577     }
10578
10579 #endif
10580
10581         /* the following call to pic16_loadFSR0 is temporary until
10582          * optimization to handle single bit assignments is added
10583          * to the function. Until then use the old safe way! -- VR */
10584
10585     if (OP_SYMBOL(left)->remat) {
10586         // access symbol directly
10587         pic16_mov2w (AOP(left), 0);
10588     } else {
10589         pic16_loadFSR0( left, 0 );
10590  
10591         /* read the first byte  */
10592         switch (ptype) {
10593                 case POINTER:
10594                 case IPOINTER:
10595                 case PPOINTER:
10596                 case FPOINTER:
10597                 case GPOINTER:
10598                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10599                         break;
10600                 case CPOINTER:
10601                         pic16_emitcode("clr","a");
10602                         pic16_emitcode("movc","a","@a+dptr");
10603                         assert (0);
10604                         break;
10605         }
10606     }
10607
10608         /* if we have bitdisplacement then it fits   */
10609         /* into this byte completely or if length is */
10610         /* less than a byte                          */
10611         if ((shCnt = SPEC_BSTR(etype)) || 
10612                 (SPEC_BLEN(etype) <= 8))  {
10613
10614                 /* shift right acc */
10615                 AccRsh(shCnt, 0);
10616
10617                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10618                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10619
10620 /* VR -- normally I would use the following, but since we use the hack,
10621  * to avoid the masking from AccRsh, why not mask it right now? */
10622
10623 /*
10624                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10625 */
10626
10627                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10628           return ;
10629         }
10630
10631
10632
10633         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10634         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10635         exit(-1);
10636
10637     /* bit field did not fit in a byte  */
10638     rlen = SPEC_BLEN(etype) - 8;
10639     pic16_aopPut(AOP(result),"a",offset++);
10640
10641     while (1)  {
10642
10643         switch (ptype) {
10644         case POINTER:
10645         case IPOINTER:
10646             pic16_emitcode("inc","%s",rname);
10647             pic16_emitcode("mov","a,@%s",rname);
10648             break;
10649             
10650         case PPOINTER:
10651             pic16_emitcode("inc","%s",rname);
10652             pic16_emitcode("movx","a,@%s",rname);
10653             break;
10654
10655         case FPOINTER:
10656             pic16_emitcode("inc","dptr");
10657             pic16_emitcode("movx","a,@dptr");
10658             break;
10659             
10660         case CPOINTER:
10661             pic16_emitcode("clr","a");
10662             pic16_emitcode("inc","dptr");
10663             pic16_emitcode("movc","a","@a+dptr");
10664             break;
10665             
10666         case GPOINTER:
10667             pic16_emitcode("inc","dptr");
10668             pic16_emitcode("lcall","__gptrget");
10669             break;
10670         }
10671
10672         rlen -= 8;            
10673         /* if we are done */
10674         if ( rlen <= 0 )
10675             break ;
10676         
10677         pic16_aopPut(AOP(result),"a",offset++);
10678                               
10679     }
10680     
10681     if (rlen) {
10682         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10683         pic16_aopPut(AOP(result),"a",offset);          
10684     }
10685     
10686     return ;
10687 }
10688
10689
10690 static void genDataPointerGet(operand *left,
10691                               operand *result,
10692                               iCode *ic)
10693 {
10694   int size, offset = 0, leoffset=0 ;
10695
10696         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10697         pic16_aopOp(result, ic, TRUE);
10698
10699         FENTRY;
10700
10701         size = AOP_SIZE(result);
10702 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10703
10704
10705 #if 0
10706         /* The following tests may save a redudant movff instruction when
10707          * accessing unions */
10708          
10709         /* if they are the same */
10710         if (operandsEqu (left, result)) {
10711                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10712                 goto release;
10713         }
10714 #endif
10715
10716 #if 0
10717         /* if they are the same registers */
10718         if (pic16_sameRegs(AOP(left),AOP(result))) {
10719                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10720                 goto release;
10721         }
10722 #endif
10723
10724 #if 1
10725         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10726                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10727                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10728                 goto release;
10729         }
10730 #endif
10731
10732
10733 #if 0
10734         if ( AOP_TYPE(left) == AOP_PCODE) {
10735                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10736                                 AOP(left)->aopu.pcop->name,
10737                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10738                                 PCOR(AOP(left)->aopu.pcop)->instance:
10739                                 PCOI(AOP(left)->aopu.pcop)->offset);
10740         }
10741 #endif
10742
10743         if(AOP(left)->aopu.pcop->type == PO_DIR)
10744                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10745
10746         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10747
10748         while (size--) {
10749                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10750                 
10751 //              pic16_DumpOp("(result)",result);
10752                 if(is_LitAOp(AOP(result))) {
10753                         pic16_mov2w(AOP(left), offset); // patch 8
10754                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10755                 } else {
10756                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10757                                 pic16_popGet(AOP(left), offset), //patch 8
10758                                 pic16_popGet(AOP(result), offset)));
10759                 }
10760
10761                 offset++;
10762                 leoffset++;
10763         }
10764
10765 release:
10766     pic16_freeAsmop(result,NULL,ic,TRUE);
10767 }
10768
10769
10770
10771 /*-----------------------------------------------------------------*/
10772 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10773 /*-----------------------------------------------------------------*/
10774 static void genNearPointerGet (operand *left, 
10775                                operand *result, 
10776                                iCode *ic)
10777 {
10778 //  asmop *aop = NULL;
10779   //regs *preg = NULL ;
10780   sym_link *rtype, *retype;
10781   sym_link *ltype = operandType(left);    
10782
10783     FENTRY;
10784     
10785     rtype = operandType(result);
10786     retype= getSpec(rtype);
10787     
10788     pic16_aopOp(left,ic,FALSE);
10789
10790 //    pic16_DumpOp("(left)",left);
10791 //    pic16_DumpOp("(result)",result);
10792
10793     /* if left is rematerialisable and
10794      * result is not bit variable type and
10795      * the left is pointer to data space i.e
10796      * lower 128 bytes of space */
10797     
10798     if (AOP_TYPE(left) == AOP_PCODE
10799       && !IS_BITFIELD(retype)
10800       && DCL_TYPE(ltype) == POINTER) {
10801
10802         genDataPointerGet (left,result,ic);
10803         pic16_freeAsmop(left, NULL, ic, TRUE);
10804         return ;
10805     }
10806     
10807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10808     pic16_aopOp (result,ic,TRUE);
10809     
10810     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10811
10812 #if 1
10813     if(IS_BITFIELD( retype )
10814       && (SPEC_BLEN(operandType(result))==1)
10815     ) {
10816       iCode *nextic;
10817       pCodeOp *jop;
10818       int bitstrt, bytestrt;
10819
10820         /* if this is bitfield of size 1, see if we are checking the value
10821          * of a single bit in an if-statement,
10822          * if yes, then don't generate usual code, but execute the
10823          * genIfx directly -- VR */
10824
10825         nextic = ic->next;
10826
10827         /* CHECK: if next iCode is IFX
10828          * and current result operand is nextic's conditional operand
10829          * and current result operand live ranges ends at nextic's key number
10830          */
10831         if((nextic->op == IFX)
10832           && (result == IC_COND(nextic))
10833           && (OP_LIVETO(result) == nextic->seq)
10834           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10835           ) {
10836             /* everything is ok then */
10837             /* find a way to optimize the genIfx iCode */
10838
10839             bytestrt = SPEC_BSTR(operandType(result))/8;
10840             bitstrt = SPEC_BSTR(operandType(result))%8;
10841             
10842             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10843
10844             genIfxpCOpJump(nextic, jop);
10845             
10846             pic16_freeAsmop(left, NULL, ic, TRUE);
10847             pic16_freeAsmop(result, NULL, ic, TRUE);
10848             return;
10849         }
10850     }
10851 #endif
10852
10853
10854     /* if the value is already in a pointer register
10855      * then don't need anything more */
10856     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
10857       /* otherwise get a free pointer register */
10858       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10859                 
10860       ;
10861     }
10862
10863     /* if bitfield then unpack the bits */
10864     if (IS_BITFIELD(retype)) 
10865       genUnpackBits (result, left, NULL, POINTER);
10866     else {
10867       /* we have can just get the values */
10868       int size = AOP_SIZE(result);
10869       int offset = 0;   
10870         
10871       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10872
10873       pic16_loadFSR0( left, 0 );
10874
10875       while(size--) {
10876         if(size) {
10877           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10878                 pic16_popGet(AOP(result), offset++)));
10879         } else {
10880           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10881                 pic16_popGet(AOP(result), offset++)));
10882         }
10883       }
10884     }
10885
10886 #if 0
10887     /* now some housekeeping stuff */
10888     if (aop) {
10889       /* we had to allocate for this iCode */
10890       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10891       pic16_freeAsmop(NULL,aop,ic,TRUE);
10892     } else { 
10893       /* we did not allocate which means left
10894        * already in a pointer register, then
10895        * if size > 0 && this could be used again
10896        * we have to point it back to where it 
10897        * belongs */
10898       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10899       if (AOP_SIZE(result) > 1
10900         && !OP_SYMBOL(left)->remat
10901         && ( OP_SYMBOL(left)->liveTo > ic->seq
10902             || ic->depth )) {
10903 //        int size = AOP_SIZE(result) - 1;
10904 //        while (size--)
10905 //          pic16_emitcode("dec","%s",rname);
10906         }
10907     }
10908 #endif
10909
10910     /* done */
10911     pic16_freeAsmop(left,NULL,ic,TRUE);
10912     pic16_freeAsmop(result,NULL,ic,TRUE);
10913 }
10914
10915 /*-----------------------------------------------------------------*/
10916 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10917 /*-----------------------------------------------------------------*/
10918 static void genPagedPointerGet (operand *left, 
10919                                operand *result, 
10920                                iCode *ic)
10921 {
10922     asmop *aop = NULL;
10923     regs *preg = NULL ;
10924     char *rname ;
10925     sym_link *rtype, *retype;    
10926
10927     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10928
10929     rtype = operandType(result);
10930     retype= getSpec(rtype);
10931     
10932     pic16_aopOp(left,ic,FALSE);
10933
10934   /* if the value is already in a pointer register
10935        then don't need anything more */
10936     if (!AOP_INPREG(AOP(left))) {
10937         /* otherwise get a free pointer register */
10938         aop = newAsmop(0);
10939         preg = getFreePtr(ic,&aop,FALSE);
10940         pic16_emitcode("mov","%s,%s",
10941                 preg->name,
10942                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10943         rname = preg->name ;
10944     } else
10945         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10946     
10947     pic16_freeAsmop(left,NULL,ic,TRUE);
10948     pic16_aopOp (result,ic,TRUE);
10949
10950     /* if bitfield then unpack the bits */
10951     if (IS_BITFIELD(retype)) 
10952         genUnpackBits (result,left,rname,PPOINTER);
10953     else {
10954         /* we have can just get the values */
10955         int size = AOP_SIZE(result);
10956         int offset = 0 ;        
10957         
10958         while (size--) {
10959             
10960             pic16_emitcode("movx","a,@%s",rname);
10961             pic16_aopPut(AOP(result),"a",offset);
10962             
10963             offset++ ;
10964             
10965             if (size)
10966                 pic16_emitcode("inc","%s",rname);
10967         }
10968     }
10969
10970     /* now some housekeeping stuff */
10971     if (aop) {
10972         /* we had to allocate for this iCode */
10973         pic16_freeAsmop(NULL,aop,ic,TRUE);
10974     } else { 
10975         /* we did not allocate which means left
10976            already in a pointer register, then
10977            if size > 0 && this could be used again
10978            we have to point it back to where it 
10979            belongs */
10980         if (AOP_SIZE(result) > 1 &&
10981             !OP_SYMBOL(left)->remat &&
10982             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10983               ic->depth )) {
10984             int size = AOP_SIZE(result) - 1;
10985             while (size--)
10986                 pic16_emitcode("dec","%s",rname);
10987         }
10988     }
10989
10990     /* done */
10991     pic16_freeAsmop(result,NULL,ic,TRUE);
10992     
10993         
10994 }
10995
10996 /*-----------------------------------------------------------------*/
10997 /* genFarPointerGet - gget value from far space                    */
10998 /*-----------------------------------------------------------------*/
10999 static void genFarPointerGet (operand *left,
11000                               operand *result, iCode *ic)
11001 {
11002     int size, offset ;
11003     sym_link *retype = getSpec(operandType(result));
11004
11005     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11006
11007     pic16_aopOp(left,ic,FALSE);
11008
11009     /* if the operand is already in dptr 
11010     then we do nothing else we move the value to dptr */
11011     if (AOP_TYPE(left) != AOP_STR) {
11012         /* if this is remateriazable */
11013         if (AOP_TYPE(left) == AOP_IMMD)
11014             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11015         else { /* we need to get it byte by byte */
11016             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11017             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11018             if (options.model == MODEL_FLAT24)
11019             {
11020                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11021             }
11022         }
11023     }
11024     /* so dptr know contains the address */
11025     pic16_freeAsmop(left,NULL,ic,TRUE);
11026     pic16_aopOp(result,ic,TRUE);
11027
11028     /* if bit then unpack */
11029     if (IS_BITFIELD(retype)) 
11030         genUnpackBits(result,left,"dptr",FPOINTER);
11031     else {
11032         size = AOP_SIZE(result);
11033         offset = 0 ;
11034
11035         while (size--) {
11036             pic16_emitcode("movx","a,@dptr");
11037             pic16_aopPut(AOP(result),"a",offset++);
11038             if (size)
11039                 pic16_emitcode("inc","dptr");
11040         }
11041     }
11042
11043     pic16_freeAsmop(result,NULL,ic,TRUE);
11044 }
11045
11046 #if 0
11047 /*-----------------------------------------------------------------*/
11048 /* genCodePointerGet - get value from code space                  */
11049 /*-----------------------------------------------------------------*/
11050 static void genCodePointerGet (operand *left,
11051                                 operand *result, iCode *ic)
11052 {
11053     int size, offset ;
11054     sym_link *retype = getSpec(operandType(result));
11055
11056     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11057
11058     pic16_aopOp(left,ic,FALSE);
11059
11060     /* if the operand is already in dptr 
11061     then we do nothing else we move the value to dptr */
11062     if (AOP_TYPE(left) != AOP_STR) {
11063         /* if this is remateriazable */
11064         if (AOP_TYPE(left) == AOP_IMMD)
11065             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11066         else { /* we need to get it byte by byte */
11067             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11068             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11069             if (options.model == MODEL_FLAT24)
11070             {
11071                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11072             }
11073         }
11074     }
11075     /* so dptr know contains the address */
11076     pic16_freeAsmop(left,NULL,ic,TRUE);
11077     pic16_aopOp(result,ic,FALSE);
11078
11079     /* if bit then unpack */
11080     if (IS_BITFIELD(retype)) 
11081         genUnpackBits(result,left,"dptr",CPOINTER);
11082     else {
11083         size = AOP_SIZE(result);
11084         offset = 0 ;
11085
11086         while (size--) {
11087             pic16_emitcode("clr","a");
11088             pic16_emitcode("movc","a,@a+dptr");
11089             pic16_aopPut(AOP(result),"a",offset++);
11090             if (size)
11091                 pic16_emitcode("inc","dptr");
11092         }
11093     }
11094
11095     pic16_freeAsmop(result,NULL,ic,TRUE);
11096 }
11097 #endif
11098
11099 #if 0
11100 /*-----------------------------------------------------------------*/
11101 /* genGenPointerGet - gget value from generic pointer space        */
11102 /*-----------------------------------------------------------------*/
11103 static void genGenPointerGet (operand *left,
11104                               operand *result, iCode *ic)
11105 {
11106   int size, offset, lit;
11107   sym_link *retype = getSpec(operandType(result));
11108
11109         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11110         pic16_aopOp(left,ic,FALSE);
11111         pic16_aopOp(result,ic,FALSE);
11112         size = AOP_SIZE(result);
11113
11114         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11115
11116         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11117
11118                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11119                 // load FSR0 from immediate
11120                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11121
11122 //              pic16_loadFSR0( left );
11123
11124                 offset = 0;
11125                 while(size--) {
11126                         if(size) {
11127                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11128                         } else {
11129                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11130                         }
11131                         offset++;
11132                 }
11133                 goto release;
11134
11135         }
11136         else { /* we need to get it byte by byte */
11137                 // set up FSR0 with address from left
11138                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11139                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11140                 
11141                 offset = 0 ;
11142
11143                 while(size--) {
11144                         if(size) {
11145                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11146                         } else {
11147                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11148                         }
11149                         offset++;
11150                 }
11151                 goto release;
11152         }
11153
11154   /* if bit then unpack */
11155         if (IS_BITFIELD(retype)) 
11156                 genUnpackBits(result,left,"BAD",GPOINTER);
11157
11158         release:
11159         pic16_freeAsmop(left,NULL,ic,TRUE);
11160         pic16_freeAsmop(result,NULL,ic,TRUE);
11161
11162 }
11163 #endif
11164
11165
11166 /*-----------------------------------------------------------------*/
11167 /* genGenPointerGet - gget value from generic pointer space        */
11168 /*-----------------------------------------------------------------*/
11169 static void genGenPointerGet (operand *left,
11170                               operand *result, iCode *ic)
11171 {
11172   int size, offset, lit;
11173   sym_link *retype = getSpec(operandType(result));
11174   char fgptrget[32];
11175
11176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11177     pic16_aopOp(left,ic,FALSE);
11178     pic16_aopOp(result,ic,TRUE);
11179     size = AOP_SIZE(result);
11180
11181     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11182
11183     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11184
11185       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11186       // load FSR0 from immediate
11187       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11188
11189       werror(W_POSSBUG2, __FILE__, __LINE__);
11190
11191       offset = 0;
11192       while(size--) {
11193         if(size) {
11194           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11195         } else {
11196           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11197         }
11198         offset++;
11199       }
11200
11201       goto release;
11202
11203     } else { /* we need to get it byte by byte */
11204
11205       /* set up WREG:PRODL:FSR0L with address from left */
11206       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11207       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11208       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11209       
11210       switch( size ) {
11211         case 1: strcpy(fgptrget, "__gptrget1"); break;
11212         case 2: strcpy(fgptrget, "__gptrget2"); break;
11213         case 3: strcpy(fgptrget, "__gptrget3"); break;
11214         case 4: strcpy(fgptrget, "__gptrget4"); break;
11215         default:
11216           werror(W_POSSBUG2, __FILE__, __LINE__);
11217           abort();
11218       }
11219       
11220       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11221       
11222       assignResultValue(result, 1);
11223       
11224       {
11225         symbol *sym;
11226
11227           sym = newSymbol( fgptrget, 0 );
11228           sym->used++;
11229           strcpy(sym->rname, fgptrget);
11230           checkAddSym(&externs, sym);
11231
11232 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11233       }
11234               
11235       goto release;
11236     }
11237
11238   /* if bit then unpack */
11239     if (IS_BITFIELD(retype)) 
11240       genUnpackBits(result,left,"BAD",GPOINTER);
11241
11242 release:
11243   pic16_freeAsmop(left,NULL,ic,TRUE);
11244   pic16_freeAsmop(result,NULL,ic,TRUE);
11245 }
11246
11247 /*-----------------------------------------------------------------*/
11248 /* genConstPointerGet - get value from const generic pointer space */
11249 /*-----------------------------------------------------------------*/
11250 static void genConstPointerGet (operand *left,
11251                                 operand *result, iCode *ic)
11252 {
11253   //sym_link *retype = getSpec(operandType(result));
11254   // symbol *albl = newiTempLabel(NULL);        // patch 15
11255   // symbol *blbl = newiTempLabel(NULL);        //
11256   // PIC_OPCODE poc;                            // patch 15
11257   int size;
11258   int offset = 0;
11259
11260   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11261   pic16_aopOp(left,ic,FALSE);
11262   pic16_aopOp(result,ic,TRUE);
11263   size = AOP_SIZE(result);
11264
11265   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11266
11267   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11268
11269   // set up table pointer
11270   if( (AOP_TYPE(left) == AOP_PCODE) 
11271       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11272           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11273     {
11274       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11275       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11276       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11277       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11278       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11279       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11280   } else {
11281     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11282     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11283     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11284   }
11285
11286   while(size--) {
11287     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11288     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11289     offset++;
11290   }
11291     
11292   pic16_freeAsmop(left,NULL,ic,TRUE);
11293   pic16_freeAsmop(result,NULL,ic,TRUE);
11294 }
11295
11296
11297 /*-----------------------------------------------------------------*/
11298 /* genPointerGet - generate code for pointer get                   */
11299 /*-----------------------------------------------------------------*/
11300 static void genPointerGet (iCode *ic)
11301 {
11302   operand *left, *result ;
11303   sym_link *type, *etype;
11304   int p_type;
11305
11306     FENTRY;
11307     
11308     left = IC_LEFT(ic);
11309     result = IC_RESULT(ic) ;
11310
11311     /* depending on the type of pointer we need to
11312     move it to the correct pointer register */
11313     type = operandType(left);
11314     etype = getSpec(type);
11315
11316 #if 0
11317     if (IS_PTR_CONST(type))
11318 #else
11319     if (IS_CODEPTR(type))
11320 #endif
11321       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11322
11323     /* if left is of type of pointer then it is simple */
11324     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11325       p_type = DCL_TYPE(type);
11326     else {
11327       /* we have to go by the storage class */
11328       p_type = PTR_TYPE(SPEC_OCLS(etype));
11329
11330       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11331
11332       if (SPEC_OCLS(etype)->codesp ) {
11333         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11334         //p_type = CPOINTER ;   
11335       } else
11336       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11337         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11338         /*p_type = FPOINTER ;*/ 
11339       } else
11340       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11341         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11342         /* p_type = PPOINTER; */
11343       } else
11344       if (SPEC_OCLS(etype) == idata ) {
11345         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11346         /* p_type = IPOINTER; */
11347       } else {
11348         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11349         /* p_type = POINTER ; */
11350       }
11351     }
11352
11353     /* now that we have the pointer type we assign
11354     the pointer values */
11355     switch (p_type) {
11356       case POINTER:     
11357       case IPOINTER:
11358         genNearPointerGet (left,result,ic);
11359         break;
11360
11361       case PPOINTER:
11362         genPagedPointerGet(left,result,ic);
11363         break;
11364
11365       case FPOINTER:
11366         genFarPointerGet (left,result,ic);
11367         break;
11368
11369       case CPOINTER:
11370         genConstPointerGet (left,result,ic);
11371         //pic16_emitcodePointerGet (left,result,ic);
11372         break;
11373
11374       case GPOINTER:
11375 #if 0
11376       if (IS_PTR_CONST(type))
11377         genConstPointerGet (left,result,ic);
11378       else
11379 #endif
11380         genGenPointerGet (left,result,ic);
11381       break;
11382
11383     default:
11384       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11385               "genPointerGet: illegal pointer type");
11386     
11387     }
11388 }
11389
11390 /*-----------------------------------------------------------------*/
11391 /* genPackBits - generates code for packed bit storage             */
11392 /*-----------------------------------------------------------------*/
11393 static void genPackBits (sym_link    *etype , operand *result,
11394                          operand *right ,
11395                          char *rname, int p_type)
11396 {
11397   int shCnt = 0 ;
11398   int offset = 0  ;
11399   int rLen = 0 ;
11400   int blen, bstr ;   
11401   sym_link *retype;
11402
11403         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11404         blen = SPEC_BLEN(etype);
11405         bstr = SPEC_BSTR(etype);
11406
11407         retype = getSpec(operandType(right));
11408
11409         if(AOP_TYPE(right) == AOP_LIT) {
11410                 if((blen == 1) && (bstr < 8)) {
11411                   unsigned long lit;
11412                         /* it is a single bit, so use the appropriate bit instructions */
11413
11414                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11415
11416                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11417 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11418                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11419                                 /* workaround to reduce the extra lfsr instruction */
11420                                 if(lit) {
11421                                         pic16_emitpcode(POC_BSF,
11422                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11423                                 } else {
11424                                         pic16_emitpcode(POC_BCF,
11425                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11426                                 }
11427                         } else {
11428                                 pic16_loadFSR0(result, 0);
11429                                 if(lit) {
11430                                         pic16_emitpcode(POC_BSF,
11431                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11432                                 } else {
11433                                         pic16_emitpcode(POC_BCF,
11434                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11435                                 }
11436                         }
11437         
11438                   return;
11439                 }
11440                 /* move literal to W */
11441                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11442                 offset++;
11443         } else
11444         if(IS_BITFIELD(retype) 
11445           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11446           && (blen == 1)) {
11447           int rblen, rbstr;
11448
11449             rblen = SPEC_BLEN( retype );
11450             rbstr = SPEC_BSTR( retype );
11451             
11452
11453             if(IS_BITFIELD(etype)) {
11454               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11455               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11456             } else {
11457               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11458             }
11459             
11460             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11461             
11462             if(IS_BITFIELD(etype)) {
11463               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11464             } else {
11465               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11466             }
11467
11468             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11469             
11470             return;
11471         } else {
11472           /* move right to W */
11473           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11474         }
11475
11476         /* if the bit length is less than or   */
11477         /* it exactly fits a byte then         */
11478         if((shCnt=SPEC_BSTR(etype))
11479                 || SPEC_BLEN(etype) <= 8 )  {
11480                 int fsr0_setup = 0;
11481
11482                 if (blen != 8 || bstr != 0) {
11483                   // we need to combine the value with the old value
11484                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11485
11486           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11487                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11488                 
11489                   /* shift left acc */
11490                   AccLsh(shCnt);
11491
11492                   /* using PRODH as a temporary register here */
11493                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11494
11495                  if (OP_SYMBOL(result)->remat) {
11496                    // access symbol directly
11497                    pic16_mov2w (AOP(result), 0);
11498                  } else {
11499                   /* get old value */
11500                   switch (p_type) {
11501                         case FPOINTER:
11502                         case POINTER:
11503                                 pic16_loadFSR0( result, 0 );
11504                                 fsr0_setup = 1;
11505                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11506 //                              pic16_emitcode ("mov","b,a");
11507 //                              pic16_emitcode("mov","a,@%s",rname);
11508                                 break;
11509
11510                         case GPOINTER:
11511                                 if (AOP(result)->aopu.aop_reg[2]) {
11512                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11513                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11514                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11515                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11516                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11517                                   {
11518                                     symbol *sym;
11519                                     sym = newSymbol( "__gptrget1", 0 );
11520                                     strcpy(sym->rname, "__gptrget1");
11521                                     checkAddSym(&externs, sym);
11522                                   }
11523                                 } else {
11524                                   // data pointer (just 2 byte given)
11525                                   pic16_loadFSR0( result, 0 );
11526                                   fsr0_setup = 1;
11527                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11528                                 }
11529                                 
11530                                 // warnings will be emitted below
11531                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11532                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11533                                 break;
11534
11535                         default:
11536                                 assert (0 && "invalid pointer type specified");
11537                                 break;
11538                   }
11539                  }
11540 #if 1
11541                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11542                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11543                                         (unsigned char)(0xff >> (8-bstr))) ));
11544                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11545                 } // if (blen != 8 || bstr != 0)
11546
11547                 /* write new value back */
11548                if (OP_SYMBOL(result)->remat) {
11549                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11550                } else {
11551                 switch (p_type) {
11552                         case FPOINTER:
11553                         case POINTER:
11554                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11555                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11556                                 break;
11557
11558                         case GPOINTER:
11559                                 if (AOP(result)->aopu.aop_reg[2]) {
11560                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11561                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11562                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11563                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11564                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11565                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11566                                   {
11567                                     symbol *sym;
11568                                     sym = newSymbol( "__gptrput1", 0 );
11569                                     strcpy(sym->rname, "__gptrput1");
11570                                     checkAddSym(&externs, sym);
11571                                   }
11572                                 } else {
11573                                   // data pointer (just 2 byte given)
11574                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11575                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11576                                 }
11577                                 
11578                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11579                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11580                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11581                                 break;
11582
11583                         default:
11584                                 assert (0 && "invalid pointer type specified");
11585                                 break;
11586                 }
11587                }
11588 #endif
11589
11590           return;
11591         }
11592
11593
11594 #if 0
11595         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11596         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11597         exit(-1);
11598 #endif
11599
11600
11601     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11602     rLen = SPEC_BLEN(etype)-8;
11603     
11604     /* now generate for lengths greater than one byte */
11605     while (1) {
11606         rLen -= 8 ;
11607         if (rLen <= 0 ) {
11608           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11609           break ;
11610         }
11611
11612         switch (p_type) {
11613             case POINTER:
11614                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11615                 break;
11616
11617 /*
11618             case FPOINTER:
11619                 MOVA(l);
11620                 pic16_emitcode("movx","@dptr,a");
11621                 break;
11622
11623             case GPOINTER:
11624                 MOVA(l);
11625                 DEBUGpic16_emitcode(";lcall","__gptrput");
11626                 break;  
11627 */
11628           default:
11629             assert(0);
11630         }   
11631
11632
11633         pic16_mov2w(AOP(right), offset++);
11634     }
11635
11636     /* last last was not complete */
11637     if (rLen)   {
11638         /* save the byte & read byte */
11639         switch (p_type) {
11640             case POINTER:
11641 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11642                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11643                 break;
11644
11645 /*
11646             case FPOINTER:
11647                 pic16_emitcode ("mov","b,a");
11648                 pic16_emitcode("movx","a,@dptr");
11649                 break;
11650
11651             case GPOINTER:
11652                 pic16_emitcode ("push","b");
11653                 pic16_emitcode ("push","acc");
11654                 pic16_emitcode ("lcall","__gptrget");
11655                 pic16_emitcode ("pop","b");
11656                 break;
11657 */
11658             default:
11659               assert(0);
11660         }
11661         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11662         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11663         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11664 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11665 //        pic16_emitcode ("orl","a,b");
11666     }
11667
11668 //    if (p_type == GPOINTER)
11669 //        pic16_emitcode("pop","b");
11670
11671     switch (p_type) {
11672
11673       case POINTER:
11674         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11675 //      pic16_emitcode("mov","@%s,a",rname);
11676         break;
11677 /*
11678       case FPOINTER:
11679         pic16_emitcode("movx","@dptr,a");
11680         break;
11681         
11682       case GPOINTER:
11683         DEBUGpic16_emitcode(";lcall","__gptrput");
11684         break;                  
11685 */
11686       default:
11687         assert(0);
11688     }
11689     
11690 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11691 }
11692 /*-----------------------------------------------------------------*/
11693 /* genDataPointerSet - remat pointer to data space                 */
11694 /*-----------------------------------------------------------------*/
11695 static void genDataPointerSet(operand *right,
11696                               operand *result,
11697                               iCode *ic)
11698 {
11699     int size, offset = 0, resoffset=0 ;
11700
11701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11702     pic16_aopOp(right,ic,FALSE);
11703
11704     size = AOP_SIZE(right);
11705
11706 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11707
11708 #if 0
11709     if ( AOP_TYPE(result) == AOP_PCODE) {
11710       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11711               AOP(result)->aopu.pcop->name,
11712                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11713               PCOR(AOP(result)->aopu.pcop)->instance:
11714               PCOI(AOP(result)->aopu.pcop)->offset);
11715     }
11716 #endif
11717
11718         if(AOP(result)->aopu.pcop->type == PO_DIR)
11719                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11720
11721         while (size--) {
11722                 if (AOP_TYPE(right) == AOP_LIT) {
11723                   unsigned int lit;
11724
11725                     if(!IS_FLOAT(operandType( right )))
11726                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11727                     else {
11728                       union {
11729                         unsigned long lit_int;
11730                         float lit_float;
11731                       } info;
11732         
11733                         /* take care if literal is a float */
11734                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11735                         lit = info.lit_int;
11736                     }
11737
11738                     lit = lit >> (8*offset);
11739                     if(lit&0xff) {
11740                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11741                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11742                     } else {
11743                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11744                     }
11745                 } else {
11746                   pic16_mov2w(AOP(right), offset);
11747                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11748                 }
11749                 offset++;
11750                 resoffset++;
11751         }
11752
11753     pic16_freeAsmop(right,NULL,ic,TRUE);
11754 }
11755
11756
11757
11758 /*-----------------------------------------------------------------*/
11759 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11760 /*-----------------------------------------------------------------*/
11761 static void genNearPointerSet (operand *right,
11762                                operand *result, 
11763                                iCode *ic)
11764 {
11765   asmop *aop = NULL;
11766   sym_link *retype;
11767   sym_link *ptype = operandType(result);
11768   sym_link *resetype;
11769     
11770         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11771         retype= getSpec(operandType(right));
11772         resetype = getSpec(operandType(result));
11773   
11774         pic16_aopOp(result,ic,FALSE);
11775     
11776         /* if the result is rematerializable &
11777          * in data space & not a bit variable */
11778         
11779         /* and result is not a bit variable */
11780         if (AOP_TYPE(result) == AOP_PCODE
11781 //              && AOP_TYPE(result) == AOP_IMMD
11782                 && DCL_TYPE(ptype) == POINTER
11783                 && !IS_BITFIELD(retype)
11784                 && !IS_BITFIELD(resetype)) {
11785
11786                 genDataPointerSet (right,result,ic);
11787                 pic16_freeAsmop(result,NULL,ic,TRUE);
11788           return;
11789         }
11790
11791         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11792         pic16_aopOp(right,ic,FALSE);
11793         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11794
11795         /* if the value is already in a pointer register
11796          * then don't need anything more */
11797         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11798           /* otherwise get a free pointer register */
11799           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11800
11801           ;
11802         }
11803
11804         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11805
11806         /* if bitfield then unpack the bits */
11807         if (IS_BITFIELD(resetype)) {
11808                 genPackBits (resetype, result, right, NULL, POINTER);
11809         } else {
11810                 /* we have can just get the values */
11811           int size = AOP_SIZE(right);
11812           int offset = 0 ;    
11813
11814             pic16_loadFSR0(result, 0);
11815             
11816                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11817                 while (size--) {
11818                                 if (AOP_TYPE(right) == AOP_LIT) {
11819                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11820                                         if (size) {
11821                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11822                                         } else {
11823                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11824                                         }
11825                                 } else { // no literal
11826                                         if(size) {
11827                                                 pic16_emitpcode(POC_MOVFF,
11828                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11829                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11830                                         } else {
11831                                                 pic16_emitpcode(POC_MOVFF,
11832                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11833                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11834                                         }
11835                                 }
11836                         offset++;
11837                 }
11838         }
11839
11840         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11841         /* now some housekeeping stuff */
11842         if (aop) {
11843           /* we had to allocate for this iCode */
11844           pic16_freeAsmop(NULL,aop,ic,TRUE);
11845         } else { 
11846           /* we did not allocate which means left
11847            * already in a pointer register, then
11848            * if size > 0 && this could be used again
11849            * we have to point it back to where it 
11850            * belongs */
11851           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11852           if (AOP_SIZE(right) > 1
11853             && !OP_SYMBOL(result)->remat
11854             && ( OP_SYMBOL(result)->liveTo > ic->seq
11855             || ic->depth )) {
11856
11857               int size = AOP_SIZE(right) - 1;
11858
11859                 while (size--)
11860                   pic16_emitcode("decf","fsr0,f");
11861                   //pic16_emitcode("dec","%s",rname);
11862             }
11863         }
11864
11865     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11866     /* done */
11867 //release:
11868     pic16_freeAsmop(right,NULL,ic,TRUE);
11869     pic16_freeAsmop(result,NULL,ic,TRUE);
11870 }
11871
11872 /*-----------------------------------------------------------------*/
11873 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11874 /*-----------------------------------------------------------------*/
11875 static void genPagedPointerSet (operand *right,
11876                                operand *result, 
11877                                iCode *ic)
11878 {
11879     asmop *aop = NULL;
11880     regs *preg = NULL ;
11881     char *rname , *l;
11882     sym_link *retype;
11883        
11884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11885
11886     retype= getSpec(operandType(right));
11887     
11888     pic16_aopOp(result,ic,FALSE);
11889     
11890     /* if the value is already in a pointer register
11891        then don't need anything more */
11892     if (!AOP_INPREG(AOP(result))) {
11893         /* otherwise get a free pointer register */
11894         aop = newAsmop(0);
11895         preg = getFreePtr(ic,&aop,FALSE);
11896         pic16_emitcode("mov","%s,%s",
11897                 preg->name,
11898                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11899         rname = preg->name ;
11900     } else
11901         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11902     
11903     pic16_freeAsmop(result,NULL,ic,TRUE);
11904     pic16_aopOp (right,ic,FALSE);
11905
11906     /* if bitfield then unpack the bits */
11907     if (IS_BITFIELD(retype)) 
11908         genPackBits (retype,result,right,rname,PPOINTER);
11909     else {
11910         /* we have can just get the values */
11911         int size = AOP_SIZE(right);
11912         int offset = 0 ;        
11913         
11914         while (size--) {
11915             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11916             
11917             MOVA(l);
11918             pic16_emitcode("movx","@%s,a",rname);
11919
11920             if (size)
11921                 pic16_emitcode("inc","%s",rname);
11922
11923             offset++;
11924         }
11925     }
11926     
11927     /* now some housekeeping stuff */
11928     if (aop) {
11929         /* we had to allocate for this iCode */
11930         pic16_freeAsmop(NULL,aop,ic,TRUE);
11931     } else { 
11932         /* we did not allocate which means left
11933            already in a pointer register, then
11934            if size > 0 && this could be used again
11935            we have to point it back to where it 
11936            belongs */
11937         if (AOP_SIZE(right) > 1 &&
11938             !OP_SYMBOL(result)->remat &&
11939             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11940               ic->depth )) {
11941             int size = AOP_SIZE(right) - 1;
11942             while (size--)
11943                 pic16_emitcode("dec","%s",rname);
11944         }
11945     }
11946
11947     /* done */
11948     pic16_freeAsmop(right,NULL,ic,TRUE);
11949     
11950         
11951 }
11952
11953 /*-----------------------------------------------------------------*/
11954 /* genFarPointerSet - set value from far space                     */
11955 /*-----------------------------------------------------------------*/
11956 static void genFarPointerSet (operand *right,
11957                               operand *result, iCode *ic)
11958 {
11959     int size, offset ;
11960     sym_link *retype = getSpec(operandType(right));
11961
11962     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11963     pic16_aopOp(result,ic,FALSE);
11964
11965     /* if the operand is already in dptr 
11966     then we do nothing else we move the value to dptr */
11967     if (AOP_TYPE(result) != AOP_STR) {
11968         /* if this is remateriazable */
11969         if (AOP_TYPE(result) == AOP_IMMD)
11970             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11971         else { /* we need to get it byte by byte */
11972             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11973             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11974             if (options.model == MODEL_FLAT24)
11975             {
11976                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11977             }
11978         }
11979     }
11980     /* so dptr know contains the address */
11981     pic16_freeAsmop(result,NULL,ic,TRUE);
11982     pic16_aopOp(right,ic,FALSE);
11983
11984     /* if bit then unpack */
11985     if (IS_BITFIELD(retype)) 
11986         genPackBits(retype,result,right,"dptr",FPOINTER);
11987     else {
11988         size = AOP_SIZE(right);
11989         offset = 0 ;
11990
11991         while (size--) {
11992             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11993             MOVA(l);
11994             pic16_emitcode("movx","@dptr,a");
11995             if (size)
11996                 pic16_emitcode("inc","dptr");
11997         }
11998     }
11999
12000     pic16_freeAsmop(right,NULL,ic,TRUE);
12001 }
12002
12003 /*-----------------------------------------------------------------*/
12004 /* genGenPointerSet - set value from generic pointer space         */
12005 /*-----------------------------------------------------------------*/
12006 #if 0
12007 static void genGenPointerSet (operand *right,
12008                               operand *result, iCode *ic)
12009 {
12010         int i, size, offset, lit;
12011         sym_link *retype = getSpec(operandType(right));
12012
12013         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12014
12015         pic16_aopOp(result,ic,FALSE);
12016         pic16_aopOp(right,ic,FALSE);
12017         size = AOP_SIZE(right);
12018         offset = 0;
12019
12020         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12021
12022         /* if the operand is already in dptr 
12023                 then we do nothing else we move the value to dptr */
12024         if (AOP_TYPE(result) != AOP_STR) {
12025                 /* if this is remateriazable */
12026                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12027                 // WARNING: anythig until "else" is untested!
12028                 if (AOP_TYPE(result) == AOP_IMMD) {
12029                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12030                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12031                         // load FSR0 from immediate
12032                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12033                         offset = 0;
12034                         while(size--) {
12035                                 if(size) {
12036                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12037                                 } else {
12038                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12039                                 }
12040                                 offset++;
12041                         }
12042                         goto release;
12043                 }
12044                 else { /* we need to get it byte by byte */
12045                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12046                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12047
12048                         // set up FSR0 with address of result
12049                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12050                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12051
12052                         /* hack hack! see if this the FSR. If so don't load W */
12053                         if(AOP_TYPE(right) != AOP_ACC) {
12054
12055                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12056
12057                                 if(AOP_TYPE(right) == AOP_LIT)
12058                                 {
12059                                         // copy literal
12060                                         // note: pic16_popGet handles sign extension
12061                                         for(i=0;i<size;i++) {
12062                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12063                                                 if(i < size-1)
12064                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12065                                                 else
12066                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12067                                         }
12068                                 } else {
12069                                         // copy regs
12070
12071                                         for(i=0;i<size;i++) {
12072                                                 if(i < size-1)
12073                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12074                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12075                                                 else
12076                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12077                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12078                                         }
12079                                 }
12080                                 goto release;
12081                         } 
12082                         // right = ACC
12083                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12084                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12085                         goto release;
12086         } // if (AOP_TYPE(result) != AOP_IMMD)
12087
12088         } // if (AOP_TYPE(result) != AOP_STR)
12089         /* so dptr know contains the address */
12090
12091
12092         /* if bit then unpack */
12093         if (IS_BITFIELD(retype)) 
12094                 genPackBits(retype,result,right,"dptr",GPOINTER);
12095         else {
12096                 size = AOP_SIZE(right);
12097                 offset = 0 ;
12098
12099                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12100
12101                 // set up FSR0 with address of result
12102                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12103                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12104         
12105                 while (size--) {
12106                         if (AOP_TYPE(right) == AOP_LIT) {
12107                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12108                                 if (size) {
12109                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12110                                 } else {
12111                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12112                                 }
12113                         } else { // no literal
12114                                 if(size) {
12115                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12116                                 } else {
12117                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12118                                 }
12119                         }
12120                         offset++;
12121                 }
12122         }
12123
12124         release:
12125         pic16_freeAsmop(right,NULL,ic,TRUE);
12126         pic16_freeAsmop(result,NULL,ic,TRUE);
12127 }
12128 #endif
12129
12130 static void genGenPointerSet (operand *right,
12131                               operand *result, iCode *ic)
12132 {
12133   int size;
12134   sym_link *retype = getSpec(operandType(right));
12135   char fgptrput[32];
12136
12137     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12138
12139     pic16_aopOp(result,ic,FALSE);
12140     pic16_aopOp(right,ic,FALSE);
12141     size = AOP_SIZE(right);
12142
12143     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12144
12145
12146     /* if bit then unpack */
12147     if (IS_BITFIELD(retype)) {
12148 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12149       genPackBits(retype,result,right,"dptr",GPOINTER);
12150       goto release;
12151     }
12152
12153     size = AOP_SIZE(right);
12154
12155     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12156
12157
12158
12159     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12160
12161     /* value of right+0 is placed on stack, which will be retrieved
12162      * by the support function this restoring the stack. The important
12163      * thing is that there is no need to manually restore stack pointer
12164      * here */
12165     pushaop(AOP(right), 0);
12166 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12167     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12168     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12169     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12170     
12171     /* load address to write to in WREG:FSR0H:FSR0L */
12172     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12173                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12174     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12175                                 pic16_popCopyReg(&pic16_pc_prodl)));
12176     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12177     
12178
12179     /* put code here */
12180     switch (size) {
12181       case 1: strcpy(fgptrput, "__gptrput1"); break;
12182       case 2: strcpy(fgptrput, "__gptrput2"); break;
12183       case 3: strcpy(fgptrput, "__gptrput3"); break;
12184       case 4: strcpy(fgptrput, "__gptrput4"); break;
12185       default:
12186         werror(W_POSSBUG2, __FILE__, __LINE__);
12187         abort();
12188     }
12189     
12190     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12191     
12192     {
12193       symbol *sym;
12194                   
12195         sym = newSymbol( fgptrput, 0 );
12196         sym->used++;
12197         strcpy(sym->rname, fgptrput);
12198         checkAddSym(&externs, sym);
12199     }
12200
12201 release:
12202     pic16_freeAsmop(right,NULL,ic,TRUE);
12203     pic16_freeAsmop(result,NULL,ic,TRUE);
12204 }
12205
12206 /*-----------------------------------------------------------------*/
12207 /* genPointerSet - stores the value into a pointer location        */
12208 /*-----------------------------------------------------------------*/
12209 static void genPointerSet (iCode *ic)
12210 {    
12211   operand *right, *result ;
12212   sym_link *type, *etype;
12213   int p_type;
12214
12215     FENTRY;
12216
12217     right = IC_RIGHT(ic);
12218     result = IC_RESULT(ic) ;
12219
12220     /* depending on the type of pointer we need to
12221     move it to the correct pointer register */
12222     type = operandType(result);
12223     etype = getSpec(type);
12224     /* if left is of type of pointer then it is simple */
12225     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12226         p_type = DCL_TYPE(type);
12227     }
12228     else {
12229         /* we have to go by the storage class */
12230         p_type = PTR_TYPE(SPEC_OCLS(etype));
12231
12232 /*      if (SPEC_OCLS(etype)->codesp ) { */
12233 /*          p_type = CPOINTER ;  */
12234 /*      } */
12235 /*      else */
12236 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12237 /*              p_type = FPOINTER ; */
12238 /*          else */
12239 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12240 /*                  p_type = PPOINTER ; */
12241 /*              else */
12242 /*                  if (SPEC_OCLS(etype) == idata ) */
12243 /*                      p_type = IPOINTER ; */
12244 /*                  else */
12245 /*                      p_type = POINTER ; */
12246     }
12247
12248     /* now that we have the pointer type we assign
12249     the pointer values */
12250     switch (p_type) {
12251       case POINTER:
12252       case IPOINTER:
12253         genNearPointerSet (right,result,ic);
12254         break;
12255
12256       case PPOINTER:
12257         genPagedPointerSet (right,result,ic);
12258         break;
12259
12260       case FPOINTER:
12261         genFarPointerSet (right,result,ic);
12262         break;
12263         
12264       case GPOINTER:
12265         genGenPointerSet (right,result,ic);
12266         break;
12267
12268       default:
12269         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12270           "genPointerSet: illegal pointer type");
12271     }
12272 }
12273
12274 /*-----------------------------------------------------------------*/
12275 /* genIfx - generate code for Ifx statement                        */
12276 /*-----------------------------------------------------------------*/
12277 static void genIfx (iCode *ic, iCode *popIc)
12278 {
12279   operand *cond = IC_COND(ic);
12280   int isbit =0;
12281
12282     FENTRY;
12283
12284     pic16_aopOp(cond,ic,FALSE);
12285
12286     /* get the value into acc */
12287     if (AOP_TYPE(cond) != AOP_CRY)
12288       pic16_toBoolean(cond);
12289     else
12290       isbit = 1;
12291     /* the result is now in the accumulator */
12292     pic16_freeAsmop(cond,NULL,ic,TRUE);
12293
12294     /* if there was something to be popped then do it */
12295     if (popIc)
12296       genIpop(popIc);
12297
12298     /* if the condition is  a bit variable */
12299     if (isbit && IS_ITEMP(cond) && 
12300         SPIL_LOC(cond)) {
12301       genIfxJump(ic,"c");
12302       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12303     } else {
12304       if (isbit && !IS_ITEMP(cond))
12305         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12306         else
12307         genIfxJump(ic,"a");
12308     }
12309     ic->generated = 1;
12310 }
12311
12312 /*-----------------------------------------------------------------*/
12313 /* genAddrOf - generates code for address of                       */
12314 /*-----------------------------------------------------------------*/
12315 static void genAddrOf (iCode *ic)
12316 {
12317   operand *result, *left;
12318   int size;
12319   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12320   pCodeOp *pcop0, *pcop1, *pcop2;
12321
12322     FENTRY;
12323
12324     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12325
12326     sym = OP_SYMBOL( IC_LEFT(ic) );
12327     
12328     if(sym->onStack) {
12329       /* get address of symbol on stack */
12330       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12331 #if 0
12332       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12333                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12334 #endif
12335
12336       // operands on stack are accessible via "FSR2 + index" with index
12337       // starting at 2 for arguments and growing from 0 downwards for
12338       // local variables (index == 0 is not assigned so we add one here)
12339       {
12340         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12341         if (soffs <= 0) {
12342           assert (soffs < 0);
12343           soffs++;
12344         } // if
12345         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12346         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12347         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12348         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12349         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12350         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12351         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12352       }
12353
12354       goto release;
12355     }
12356         
12357 //      if(pic16_debug_verbose) {
12358 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12359 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12360 //      }
12361         
12362     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12363     size = AOP_SIZE(IC_RESULT(ic));
12364
12365     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12366     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12367     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12368         
12369     if (size == 3) {
12370       pic16_emitpcode(POC_MOVLW, pcop0);
12371       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12372       pic16_emitpcode(POC_MOVLW, pcop1);
12373       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12374       pic16_emitpcode(POC_MOVLW, pcop2);
12375       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12376     } else
12377     if (size == 2) {
12378       pic16_emitpcode(POC_MOVLW, pcop0);
12379       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12380       pic16_emitpcode(POC_MOVLW, pcop1);
12381     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12382     } else {
12383       pic16_emitpcode(POC_MOVLW, pcop0);
12384       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12385     }
12386
12387     pic16_freeAsmop(left, NULL, ic, FALSE);
12388 release:
12389     pic16_freeAsmop(result,NULL,ic,TRUE);
12390 }
12391
12392
12393 #if 0
12394 /*-----------------------------------------------------------------*/
12395 /* genFarFarAssign - assignment when both are in far space         */
12396 /*-----------------------------------------------------------------*/
12397 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12398 {
12399     int size = AOP_SIZE(right);
12400     int offset = 0;
12401     char *l ;
12402     /* first push the right side on to the stack */
12403     while (size--) {
12404         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12405         MOVA(l);
12406         pic16_emitcode ("push","acc");
12407     }
12408     
12409     pic16_freeAsmop(right,NULL,ic,FALSE);
12410     /* now assign DPTR to result */
12411     pic16_aopOp(result,ic,FALSE);
12412     size = AOP_SIZE(result);
12413     while (size--) {
12414         pic16_emitcode ("pop","acc");
12415         pic16_aopPut(AOP(result),"a",--offset);
12416     }
12417     pic16_freeAsmop(result,NULL,ic,FALSE);
12418         
12419 }
12420 #endif
12421
12422 /*-----------------------------------------------------------------*/
12423 /* genAssign - generate code for assignment                        */
12424 /*-----------------------------------------------------------------*/
12425 static void genAssign (iCode *ic)
12426 {
12427   operand *result, *right;
12428   int size, offset,know_W;
12429   unsigned long lit = 0L;
12430
12431   result = IC_RESULT(ic);
12432   right  = IC_RIGHT(ic) ;
12433
12434   FENTRY;
12435   
12436   /* if they are the same */
12437   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12438     return ;
12439
12440   /* reversed order operands are aopOp'ed so that result operand
12441    * is effective in case right is a stack symbol. This maneauver
12442    * allows to use the _G.resDirect flag later */
12443   pic16_aopOp(result,ic,TRUE);
12444   pic16_aopOp(right,ic,FALSE);
12445
12446   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12447
12448   /* if they are the same registers */
12449   if (pic16_sameRegs(AOP(right),AOP(result)))
12450     goto release;
12451
12452   /* if the result is a bit */
12453   if (AOP_TYPE(result) == AOP_CRY) {
12454     /* if the right size is a literal then
12455        we know what the value is */
12456     if (AOP_TYPE(right) == AOP_LIT) {
12457           
12458       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12459                   pic16_popGet(AOP(result),0));
12460
12461       if (((int) operandLitValue(right))) 
12462         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12463                        AOP(result)->aopu.aop_dir,
12464                        AOP(result)->aopu.aop_dir);
12465       else
12466         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12467                        AOP(result)->aopu.aop_dir,
12468                        AOP(result)->aopu.aop_dir);
12469       goto release;
12470     }
12471
12472     /* the right is also a bit variable */
12473     if (AOP_TYPE(right) == AOP_CRY) {
12474       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12475       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12476       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12477
12478       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12479                      AOP(result)->aopu.aop_dir,
12480                      AOP(result)->aopu.aop_dir);
12481       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12482                      AOP(right)->aopu.aop_dir,
12483                      AOP(right)->aopu.aop_dir);
12484       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12485                      AOP(result)->aopu.aop_dir,
12486                      AOP(result)->aopu.aop_dir);
12487       goto release ;
12488     }
12489
12490     /* we need to or */
12491     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12492     pic16_toBoolean(right);
12493     emitSKPZ;
12494     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12495     //pic16_aopPut(AOP(result),"a",0);
12496     goto release ;
12497   }
12498
12499   /* bit variables done */
12500   /* general case */
12501   size = AOP_SIZE(result);
12502   offset = 0 ;
12503
12504   if(AOP_TYPE(right) == AOP_LIT) {
12505         if(!IS_FLOAT(operandType( right )))
12506                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12507         else {
12508            union {
12509               unsigned long lit_int;
12510               float lit_float;
12511             } info;
12512         
12513                 /* take care if literal is a float */
12514                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12515                 lit = info.lit_int;
12516         }
12517   }
12518
12519 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12520 //                      sizeof(unsigned long int), sizeof(float));
12521
12522
12523   if (AOP_TYPE(right) == AOP_REG) {
12524     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12525     while (size--) {
12526       
12527       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12528     } // while
12529     goto release;
12530   }
12531
12532   if(AOP_TYPE(right) != AOP_LIT
12533         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12534         && !IS_FUNC(OP_SYM_TYPE(right))
12535         ) {
12536         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12537         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12538
12539         // set up table pointer
12540         if(is_LitOp(right)) {
12541 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12542                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12543                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12544                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12545                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12546                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12547                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12548         } else {
12549 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12550                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12551                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12552                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12553                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12554                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12555                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12556         }
12557
12558         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12559         while(size--) {
12560                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12561                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12562                         pic16_popGet(AOP(result),offset)));
12563                 offset++;
12564         }
12565
12566         size = getSize(OP_SYM_ETYPE(right));
12567         if(AOP_SIZE(result) > size) {
12568                 size = AOP_SIZE(result) - size;
12569                 while(size--) {
12570                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12571                         offset++;
12572                 }
12573         }
12574         goto release;
12575   }
12576
12577
12578
12579 #if 0
12580 /* VR - What is this?! */
12581   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12582     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12583     if(aopIdx(AOP(result),0) == 4) {
12584
12585       /* this is a workaround to save value of right into wreg too,
12586        * value of wreg is going to be used later */
12587       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12588       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12589       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12590       goto release;
12591     } else
12592 //      assert(0);
12593       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12594   }
12595 #endif
12596
12597   know_W=-1;
12598   while (size--) {
12599   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12600     if(AOP_TYPE(right) == AOP_LIT) {
12601       if(lit&0xff) {
12602         if(know_W != (lit&0xff))
12603           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12604         know_W = lit&0xff;
12605         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12606       } else
12607         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12608
12609       lit >>= 8;
12610
12611     } else if (AOP_TYPE(right) == AOP_CRY) {
12612       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12613       if(offset == 0) {
12614         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12615         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12616         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12617       }
12618     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12619         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12620         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12621     } else {
12622       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12623
12624       if(!_G.resDirect)         /* use this aopForSym feature */
12625         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12626     }
12627             
12628     offset++;
12629   }
12630   
12631  release:
12632   pic16_freeAsmop (right,NULL,ic,FALSE);
12633   pic16_freeAsmop (result,NULL,ic,TRUE);
12634 }   
12635
12636 /*-----------------------------------------------------------------*/
12637 /* genJumpTab - generates code for jump table                       */
12638 /*-----------------------------------------------------------------*/
12639 static void genJumpTab (iCode *ic)
12640 {
12641   symbol *jtab;
12642   char *l;
12643   pCodeOp *jt_offs;
12644   pCodeOp *jt_offs_hi;
12645   pCodeOp *jt_label;
12646
12647     FENTRY;
12648
12649     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12650     /* get the condition into accumulator */
12651     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12652     MOVA(l);
12653     /* multiply by three */
12654     pic16_emitcode("add","a,acc");
12655     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12656
12657     jtab = newiTempLabel(NULL);
12658     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12659     pic16_emitcode("jmp","@a+dptr");
12660     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12661
12662 #if 0
12663     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12664     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12665     emitSKPNC;
12666     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12667     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12668     pic16_emitpLabel(jtab->key);
12669
12670 #else
12671
12672     jt_offs = pic16_popGetTempReg(0);
12673     jt_offs_hi = pic16_popGetTempReg(1);
12674     jt_label = pic16_popGetLabel (jtab->key);
12675     //fprintf (stderr, "Creating jump table...\n");
12676
12677     // calculate offset into jump table (idx * sizeof (GOTO))
12678     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12679     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12680     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12681     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12682     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12683     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12684     pic16_emitpcode(POC_MOVWF , jt_offs);
12685
12686     // prepare PCLATx (set to first entry in jump table)
12687     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12688     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12689     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12690     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12691     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12692
12693     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12694     pic16_emitpcode(POC_ADDWF , jt_offs);
12695     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12696     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12697     emitSKPNC;
12698     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12699
12700     // release temporaries and prepare jump into table (new PCL --> WREG)
12701     pic16_emitpcode(POC_MOVFW , jt_offs);
12702     pic16_popReleaseTempReg (jt_offs_hi, 1);
12703     pic16_popReleaseTempReg (jt_offs, 0);
12704
12705     // jump into the table
12706     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12707
12708     pic16_emitpLabelFORCE(jtab->key);
12709 #endif
12710
12711     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12712 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12713
12714     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12715     /* now generate the jump labels */
12716     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12717          jtab = setNextItem(IC_JTLABELS(ic))) {
12718 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12719         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12720         
12721     }
12722     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12723
12724 }
12725
12726 /*-----------------------------------------------------------------*/
12727 /* genMixedOperation - gen code for operators between mixed types  */
12728 /*-----------------------------------------------------------------*/
12729 /*
12730   TSD - Written for the PIC port - but this unfortunately is buggy.
12731   This routine is good in that it is able to efficiently promote 
12732   types to different (larger) sizes. Unfortunately, the temporary
12733   variables that are optimized out by this routine are sometimes
12734   used in other places. So until I know how to really parse the 
12735   iCode tree, I'm going to not be using this routine :(.
12736 */
12737 static int genMixedOperation (iCode *ic)
12738 {
12739 #if 0
12740   operand *result = IC_RESULT(ic);
12741   sym_link *ctype = operandType(IC_LEFT(ic));
12742   operand *right = IC_RIGHT(ic);
12743   int ret = 0;
12744   int big,small;
12745   int offset;
12746
12747   iCode *nextic;
12748   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12749
12750   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12751
12752   nextic = ic->next;
12753   if(!nextic)
12754     return 0;
12755
12756   nextright = IC_RIGHT(nextic);
12757   nextleft  = IC_LEFT(nextic);
12758   nextresult = IC_RESULT(nextic);
12759
12760   pic16_aopOp(right,ic,FALSE);
12761   pic16_aopOp(result,ic,FALSE);
12762   pic16_aopOp(nextright,  nextic, FALSE);
12763   pic16_aopOp(nextleft,   nextic, FALSE);
12764   pic16_aopOp(nextresult, nextic, FALSE);
12765
12766   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12767
12768     operand *t = right;
12769     right = nextright;
12770     nextright = t; 
12771
12772     pic16_emitcode(";remove right +","");
12773
12774   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12775 /*
12776     operand *t = right;
12777     right = nextleft;
12778     nextleft = t; 
12779 */
12780     pic16_emitcode(";remove left +","");
12781   } else
12782     return 0;
12783
12784   big = AOP_SIZE(nextleft);
12785   small = AOP_SIZE(nextright);
12786
12787   switch(nextic->op) {
12788
12789   case '+':
12790     pic16_emitcode(";optimize a +","");
12791     /* if unsigned or not an integral type */
12792     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12793       pic16_emitcode(";add a bit to something","");
12794     } else {
12795
12796       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12797
12798       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12799         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12800         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12801       } else
12802         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12803
12804       offset = 0;
12805       while(--big) {
12806
12807         offset++;
12808
12809         if(--small) {
12810           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12811             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12812             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12813           }
12814
12815           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12816           emitSKPNC;
12817           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12818                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12819                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12820           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12821           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12822
12823         } else {
12824           pic16_emitcode("rlf","known_zero,w");
12825
12826           /*
12827             if right is signed
12828               btfsc  right,7
12829                addlw ff
12830           */
12831           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12832             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12833             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12834           } else {
12835             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12836           }
12837         }
12838       }
12839       ret = 1;
12840     }
12841   }
12842   ret = 1;
12843
12844 release:
12845   pic16_freeAsmop(right,NULL,ic,TRUE);
12846   pic16_freeAsmop(result,NULL,ic,TRUE);
12847   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12848   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12849   if(ret)
12850     nextic->generated = 1;
12851
12852   return ret;
12853 #else
12854   return 0;
12855 #endif
12856 }
12857 /*-----------------------------------------------------------------*/
12858 /* genCast - gen code for casting                                  */
12859 /*-----------------------------------------------------------------*/
12860 static void genCast (iCode *ic)
12861 {
12862   operand *result = IC_RESULT(ic);
12863   sym_link *ctype = operandType(IC_LEFT(ic));
12864   sym_link *rtype = operandType(IC_RIGHT(ic));
12865   sym_link *restype = operandType(IC_RESULT(ic));
12866   operand *right = IC_RIGHT(ic);
12867   int size, offset ;
12868
12869
12870     FENTRY;
12871
12872         /* if they are equivalent then do nothing */
12873 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12874 //              return ;
12875
12876         pic16_aopOp(result,ic,FALSE);
12877         pic16_aopOp(right,ic,FALSE) ;
12878
12879         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12880
12881
12882         /* if the result is a bit */
12883         if (AOP_TYPE(result) == AOP_CRY) {
12884         
12885                 /* if the right size is a literal then
12886                  * we know what the value is */
12887                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12888
12889                 if (AOP_TYPE(right) == AOP_LIT) {
12890                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12891                                 pic16_popGet(AOP(result),0));
12892
12893                         if (((int) operandLitValue(right))) 
12894                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12895                                         AOP(result)->aopu.aop_dir,
12896                                         AOP(result)->aopu.aop_dir);
12897                         else
12898                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12899                                         AOP(result)->aopu.aop_dir,
12900                                         AOP(result)->aopu.aop_dir);
12901                         goto release;
12902                 }
12903
12904                 /* the right is also a bit variable */
12905                 if (AOP_TYPE(right) == AOP_CRY) {
12906                         emitCLRC;
12907                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12908
12909                         pic16_emitcode("clrc","");
12910                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12911                                 AOP(right)->aopu.aop_dir,
12912                                 AOP(right)->aopu.aop_dir);
12913                         pic16_aopPut(AOP(result),"c",0);
12914                         goto release ;
12915                 }
12916
12917                 /* we need to or */
12918                 if (AOP_TYPE(right) == AOP_REG) {
12919                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12920                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12921                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12922                 }
12923                 pic16_toBoolean(right);
12924                 pic16_aopPut(AOP(result),"a",0);
12925                 goto release ;
12926         }
12927
12928         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12929           int offset = 1;
12930
12931                 size = AOP_SIZE(result);
12932
12933                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12934
12935                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12936                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12937                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12938
12939                 while (size--)
12940                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12941
12942                 goto release;
12943         }
12944
12945         if(IS_BITFIELD(getSpec(restype))
12946           && IS_BITFIELD(getSpec(rtype))) {
12947           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12948         }
12949
12950         /* if they are the same size : or less */
12951         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12952
12953                 /* if they are in the same place */
12954                 if (pic16_sameRegs(AOP(right),AOP(result)))
12955                         goto release;
12956
12957                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12958 #if 0
12959                 if (IS_PTR_CONST(rtype))
12960 #else
12961                 if (IS_CODEPTR(rtype))
12962 #endif
12963                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12964
12965 #if 0
12966                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12967 #else
12968                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12969 #endif
12970                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12971
12972 #if 0
12973                 if(AOP_TYPE(right) == AOP_IMMD) {
12974                   pCodeOp *pcop0, *pcop1, *pcop2;
12975                   symbol *sym = OP_SYMBOL( right );
12976
12977                         size = AOP_SIZE(result);
12978                         /* low */
12979                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12980                         /* high */
12981                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12982                         /* upper */
12983                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12984         
12985                         if (size == 3) {
12986                                 pic16_emitpcode(POC_MOVLW, pcop0);
12987                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12988                                 pic16_emitpcode(POC_MOVLW, pcop1);
12989                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12990                                 pic16_emitpcode(POC_MOVLW, pcop2);
12991                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12992                         } else
12993                         if (size == 2) {
12994                                 pic16_emitpcode(POC_MOVLW, pcop0);
12995                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12996                                 pic16_emitpcode(POC_MOVLW, pcop1);
12997                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12998                         } else {
12999                                 pic16_emitpcode(POC_MOVLW, pcop0);
13000                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13001                         }
13002                 } else
13003 #endif
13004                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13005                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13006                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13007                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13008                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13009                         if(AOP_SIZE(result) <2)
13010                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13011                 } else {
13012                         /* if they in different places then copy */
13013                         size = AOP_SIZE(result);
13014                         offset = 0 ;
13015                         while (size--) {
13016                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13017                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13018                                 offset++;
13019                         }
13020                 }
13021                 goto release;
13022         }
13023
13024         /* if the result is of type pointer */
13025         if (IS_PTR(ctype)) {
13026           int p_type;
13027           sym_link *type = operandType(right);
13028           sym_link *etype = getSpec(type);
13029
13030                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13031
13032                 /* pointer to generic pointer */
13033                 if (IS_GENPTR(ctype)) {
13034                   char *l = zero;
13035             
13036                         if (IS_PTR(type)) 
13037                                 p_type = DCL_TYPE(type);
13038                         else {
13039                 /* we have to go by the storage class */
13040                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13041
13042 /*              if (SPEC_OCLS(etype)->codesp )  */
13043 /*                  p_type = CPOINTER ;  */
13044 /*              else */
13045 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13046 /*                      p_type = FPOINTER ; */
13047 /*                  else */
13048 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13049 /*                          p_type = PPOINTER; */
13050 /*                      else */
13051 /*                          if (SPEC_OCLS(etype) == idata ) */
13052 /*                              p_type = IPOINTER ; */
13053 /*                          else */
13054 /*                              p_type = POINTER ; */
13055             }
13056                 
13057             /* the first two bytes are known */
13058       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13059             size = GPTRSIZE - 1; 
13060             offset = 0 ;
13061             while (size--) {
13062               if(offset < AOP_SIZE(right)) {
13063                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13064                 mov2f(AOP(result), AOP(right), offset);
13065 /*
13066                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13067                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13068                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13069                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13070                 } else { 
13071                   
13072                   pic16_aopPut(AOP(result),
13073                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13074                          offset);
13075                 }
13076 */
13077               } else 
13078                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13079               offset++;
13080             }
13081             /* the last byte depending on type */
13082             switch (p_type) {
13083             case IPOINTER:
13084             case POINTER:
13085                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13086                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13087 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13088                 break;
13089
13090             case CPOINTER:
13091                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13092                 break;
13093
13094             case FPOINTER:
13095               pic16_emitcode(";BUG!? ","%d",__LINE__);
13096                 l = one;
13097                 break;
13098             case PPOINTER:
13099               pic16_emitcode(";BUG!? ","%d",__LINE__);
13100                 l = "#0x03";
13101                 break;
13102
13103             case GPOINTER:
13104                 if (GPTRSIZE > AOP_SIZE(right)) {
13105                   // assume data pointer... THIS MIGHT BE WRONG!
13106                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13107                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13108                 } else {
13109                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13110                 }
13111               break;
13112               
13113             default:
13114                 /* this should never happen */
13115                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13116                        "got unknown pointer type");
13117                 exit(1);
13118             }
13119             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13120             goto release ;
13121         }
13122         
13123         
13124         assert( 0 );
13125         /* just copy the pointers */
13126         size = AOP_SIZE(result);
13127         offset = 0 ;
13128         while (size--) {
13129             pic16_aopPut(AOP(result),
13130                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13131                    offset);
13132             offset++;
13133         }
13134         goto release ;
13135     }
13136     
13137
13138
13139     /* so we now know that the size of destination is greater
13140     than the size of the source.
13141     Now, if the next iCode is an operator then we might be
13142     able to optimize the operation without performing a cast.
13143     */
13144     if(genMixedOperation(ic))
13145       goto release;
13146
13147     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13148     
13149     /* we move to result for the size of source */
13150     size = AOP_SIZE(right);
13151     offset = 0 ;
13152
13153     while (size--) {
13154       if(!_G.resDirect)
13155         mov2f(AOP(result), AOP(right), offset);
13156       offset++;
13157     }
13158
13159     /* now depending on the sign of the destination */
13160     size = AOP_SIZE(result) - AOP_SIZE(right);
13161     /* if unsigned or not an integral type */
13162     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13163       while (size--)
13164         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13165     } else {
13166       /* we need to extend the sign :( */
13167
13168       if(size == 1) {
13169         /* Save one instruction of casting char to int */
13170         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13171         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13172         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13173       } else {
13174         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13175
13176         if(offset)
13177           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13178         else
13179           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13180         
13181         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13182
13183         while (size--)
13184           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13185       }
13186     }
13187
13188 release:
13189     pic16_freeAsmop(right,NULL,ic,TRUE);
13190     pic16_freeAsmop(result,NULL,ic,TRUE);
13191
13192 }
13193
13194 /*-----------------------------------------------------------------*/
13195 /* genDjnz - generate decrement & jump if not zero instrucion      */
13196 /*-----------------------------------------------------------------*/
13197 static int genDjnz (iCode *ic, iCode *ifx)
13198 {
13199     symbol *lbl, *lbl1;
13200     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13201
13202     if (!ifx)
13203         return 0;
13204     
13205     /* if the if condition has a false label
13206        then we cannot save */
13207     if (IC_FALSE(ifx))
13208         return 0;
13209
13210     /* if the minus is not of the form 
13211        a = a - 1 */
13212     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13213         !IS_OP_LITERAL(IC_RIGHT(ic)))
13214         return 0;
13215
13216     if (operandLitValue(IC_RIGHT(ic)) != 1)
13217         return 0;
13218
13219     /* if the size of this greater than one then no
13220        saving */
13221     if (getSize(operandType(IC_RESULT(ic))) > 1)
13222         return 0;
13223
13224     /* otherwise we can save BIG */
13225     lbl = newiTempLabel(NULL);
13226     lbl1= newiTempLabel(NULL);
13227
13228     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13229     
13230     if (IS_AOP_PREG(IC_RESULT(ic))) {
13231         pic16_emitcode("dec","%s",
13232                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13233         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13234         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13235     } else {    
13236
13237
13238       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13239       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13240
13241       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13242       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13243
13244     }
13245     
13246     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13247     ifx->generated = 1;
13248     return 1;
13249 }
13250
13251 /*-----------------------------------------------------------------*/
13252 /* genReceive - generate code for a receive iCode                  */
13253 /*-----------------------------------------------------------------*/
13254 static void genReceive (iCode *ic)
13255 {    
13256
13257   FENTRY;
13258
13259 #if 0
13260   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13261         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13262 #endif
13263 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13264
13265   if (isOperandInFarSpace(IC_RESULT(ic))
13266       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13267           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13268
13269     int size = getSize(operandType(IC_RESULT(ic)));
13270     int offset =  pic16_fReturnSizePic - size;
13271
13272       assert( 0 );
13273       while (size--) {
13274         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13275                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13276                       offset++;
13277         }
13278
13279       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13280
13281       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13282       size = AOP_SIZE(IC_RESULT(ic));
13283       offset = 0;
13284       while (size--) {
13285         pic16_emitcode ("pop","acc");
13286         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13287       }
13288   } else {
13289     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13290     _G.accInUse++;
13291     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13292     _G.accInUse--;
13293
13294     /* set pseudo stack pointer to where it should be - dw*/
13295     GpsuedoStkPtr = ic->parmBytes;
13296
13297     /* setting GpsuedoStkPtr has side effects here: */
13298     assignResultValue(IC_RESULT(ic), 0);
13299   }
13300
13301   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13302 }
13303
13304 /*-----------------------------------------------------------------*/
13305 /* genDummyRead - generate code for dummy read of volatiles        */
13306 /*-----------------------------------------------------------------*/
13307 static void
13308 genDummyRead (iCode * ic)
13309 {
13310   operand *op;
13311   int i;
13312
13313   op = IC_RIGHT(ic);
13314   if (op && IS_SYMOP(op)) {
13315     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13316       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13317       return;
13318     }
13319     pic16_aopOp (op, ic, FALSE);
13320     for (i=0; i < AOP_SIZE(op); i++) {
13321       // may need to protect this from the peepholer -- this is not nice but works...
13322       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13323       pic16_mov2w (AOP(op),i);
13324       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13325     } // for i
13326     pic16_freeAsmop (op, NULL, ic, TRUE);
13327   } else if (op) {
13328     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13329   } // if
13330 }
13331
13332 /*-----------------------------------------------------------------*/
13333 /* genpic16Code - generate code for pic16 based controllers        */
13334 /*-----------------------------------------------------------------*/
13335 /*
13336  * At this point, ralloc.c has gone through the iCode and attempted
13337  * to optimize in a way suitable for a PIC. Now we've got to generate
13338  * PIC instructions that correspond to the iCode.
13339  *
13340  * Once the instructions are generated, we'll pass through both the
13341  * peep hole optimizer and the pCode optimizer.
13342  *-----------------------------------------------------------------*/
13343
13344 void genpic16Code (iCode *lic)
13345 {
13346   iCode *ic;
13347   int cln = 0;
13348
13349     lineHead = lineCurr = NULL;
13350
13351     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13352     pic16_addpBlock(pb);
13353
13354 #if 0
13355     /* if debug information required */
13356     if (options.debug && currFunc) {
13357       if (currFunc) {
13358         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13359       }
13360     }
13361 #endif
13362
13363     for (ic = lic ; ic ; ic = ic->next ) {
13364
13365       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13366       if ( cln != ic->lineno ) {
13367         if ( options.debug ) {
13368           debugFile->writeCLine (ic);
13369         }
13370         
13371         if(!options.noCcodeInAsm) {
13372           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13373               printCLine(ic->filename, ic->lineno)));
13374         }
13375
13376         cln = ic->lineno ;
13377       }
13378         
13379       if(options.iCodeInAsm) {
13380         char *l;
13381
13382           /* insert here code to print iCode as comment */
13383           l = Safe_strdup(printILine(ic));
13384           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13385       }
13386         
13387       /* if the result is marked as
13388        * spilt and rematerializable or code for
13389        * this has already been generated then
13390        * do nothing */
13391       if (resultRemat(ic) || ic->generated ) 
13392         continue ;
13393         
13394       /* depending on the operation */
13395       switch (ic->op) {
13396         case '!' :
13397           pic16_genNot(ic);
13398           break;
13399             
13400         case '~' :
13401           pic16_genCpl(ic);
13402           break;
13403             
13404         case UNARYMINUS:
13405           genUminus (ic);
13406           break;
13407             
13408         case IPUSH:
13409           genIpush (ic);
13410           break;
13411             
13412         case IPOP:
13413           /* IPOP happens only when trying to restore a 
13414            * spilt live range, if there is an ifx statement
13415            * following this pop then the if statement might
13416            * be using some of the registers being popped which
13417            * would destroy the contents of the register so
13418            * we need to check for this condition and handle it */
13419            if (ic->next
13420              && ic->next->op == IFX
13421              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13422                genIfx (ic->next,ic);
13423           else
13424             genIpop (ic);
13425           break; 
13426             
13427         case CALL:
13428           genCall (ic);
13429           break;
13430             
13431         case PCALL:
13432           genPcall (ic);
13433           break;
13434             
13435         case FUNCTION:
13436           genFunction (ic);
13437           break;
13438             
13439         case ENDFUNCTION:
13440           genEndFunction (ic);
13441           break;
13442             
13443         case RETURN:
13444           genRet (ic);
13445           break;
13446             
13447         case LABEL:
13448           genLabel (ic);
13449           break;
13450             
13451         case GOTO:
13452           genGoto (ic);
13453           break;
13454             
13455         case '+' :
13456           pic16_genPlus (ic) ;
13457           break;
13458             
13459         case '-' :
13460           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13461             pic16_genMinus (ic);
13462           break;
13463
13464         case '*' :
13465           genMult (ic);
13466           break;
13467             
13468         case '/' :
13469           genDiv (ic) ;
13470           break;
13471             
13472         case '%' :
13473           genMod (ic);
13474           break;
13475             
13476         case '>' :
13477           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13478           break;
13479             
13480         case '<' :
13481           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13482           break;
13483             
13484         case LE_OP:
13485         case GE_OP:
13486         case NE_OP:
13487           /* note these two are xlated by algebraic equivalence
13488            * during parsing SDCC.y */
13489           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13490             "got '>=' or '<=' shouldn't have come here");
13491           break;
13492
13493         case EQ_OP:
13494           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13495           break;            
13496             
13497         case AND_OP:
13498           genAndOp (ic);
13499           break;
13500             
13501         case OR_OP:
13502           genOrOp (ic);
13503           break;
13504             
13505         case '^' :
13506           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13507           break;
13508             
13509         case '|' :
13510           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13511           break;
13512             
13513         case BITWISEAND:
13514           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13515           break;
13516             
13517         case INLINEASM:
13518           genInline (ic);
13519           break;
13520             
13521         case RRC:
13522           genRRC (ic);
13523           break;
13524             
13525         case RLC:
13526           genRLC (ic);
13527           break;
13528             
13529         case GETHBIT:
13530           genGetHbit (ic);
13531           break;
13532             
13533         case LEFT_OP:
13534           genLeftShift (ic);
13535           break;
13536             
13537         case RIGHT_OP:
13538           genRightShift (ic);
13539           break;
13540             
13541         case GET_VALUE_AT_ADDRESS:
13542           genPointerGet(ic);
13543           break;
13544             
13545         case '=' :
13546           if (POINTER_SET(ic))
13547             genPointerSet(ic);
13548           else
13549             genAssign(ic);
13550           break;
13551             
13552         case IFX:
13553           genIfx (ic,NULL);
13554           break;
13555             
13556         case ADDRESS_OF:
13557           genAddrOf (ic);
13558           break;
13559             
13560         case JUMPTABLE:
13561           genJumpTab (ic);
13562           break;
13563             
13564         case CAST:
13565           genCast (ic);
13566           break;
13567             
13568         case RECEIVE:
13569           genReceive(ic);
13570           break;
13571             
13572         case SEND:
13573           addSet(&_G.sendSet,ic);
13574           break;
13575
13576         case DUMMY_READ_VOLATILE:
13577           genDummyRead (ic);
13578           break;
13579
13580         default :
13581           ic = ic;
13582       }
13583     }
13584
13585
13586     /* now we are ready to call the
13587        peep hole optimizer */
13588     if (!options.nopeep)
13589       peepHole (&lineHead);
13590
13591     /* now do the actual printing */
13592     printLine (lineHead, codeOutFile);
13593
13594 #ifdef PCODE_DEBUG
13595     DFPRINTF((stderr,"printing pBlock\n\n"));
13596     pic16_printpBlock(stdout,pb);
13597 #endif
13598
13599     return;
13600 }
13601