3164667a94c7ea4a162468ce7802475107a2ca28
[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     emitSKPNC;
4841   else
4842     emitSKPC;
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 why 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   if (ifx) {
5174     //DEBUGpc ("generate control flow");
5175     genSkipc (&rIfx);
5176     ifx->generated = 1;
5177   } // if
5178 }
5179
5180 #elif 1         /* } */
5181                 /* { */
5182       /* original code */
5183 static void genCmp (operand *left,operand *right,
5184                     operand *result, iCode *ifx, int sign)
5185 {
5186   int size; //, offset = 0 ;
5187   unsigned long lit = 0L,i = 0;
5188   resolvedIfx rFalseIfx;
5189   //  resolvedIfx rTrueIfx;
5190   symbol *truelbl;
5191   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5192 /*
5193   if(ifx) {
5194     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5195     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5196   }
5197 */
5198
5199   FENTRY;
5200   
5201   resolveIfx(&rFalseIfx,ifx);
5202   truelbl  = newiTempLabel(NULL);
5203   size = max(AOP_SIZE(left),AOP_SIZE(right));
5204
5205   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5206
5207 #define _swapp
5208
5209   /* if literal is on the right then swap with left */
5210   if ((AOP_TYPE(right) == AOP_LIT)) {
5211     operand *tmp = right ;
5212     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5213     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5214 #ifdef _swapp
5215
5216     lit = (lit - 1) & mask;
5217     right = left;
5218     left = tmp;
5219     rFalseIfx.condition ^= 1;
5220 #endif
5221
5222   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5223     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5224   }
5225
5226
5227   //if(IC_TRUE(ifx) == NULL)
5228   /* if left & right are bit variables */
5229   if (AOP_TYPE(left) == AOP_CRY &&
5230       AOP_TYPE(right) == AOP_CRY ) {
5231     assert (0 && "bit variables used in genCmp");
5232     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5233     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5234   } else {
5235     /* subtract right from left if at the
5236        end the carry flag is set then we know that
5237        left is greater than right */
5238
5239     symbol *lbl  = newiTempLabel(NULL);
5240
5241 #if 0
5242         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5243                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5244 #endif
5245
5246 #ifndef _swapp
5247     if(AOP_TYPE(right) == AOP_LIT) {
5248
5249       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5250
5251       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5252
5253       /* special cases */
5254
5255       if(lit == 0) {
5256
5257         if(sign != 0) 
5258           genSkipCond(&rFalseIfx,left,size-1,7);
5259         else 
5260           /* no need to compare to 0...*/
5261           /* NOTE: this is a de-generate compare that most certainly 
5262            *       creates some dead code. */
5263           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5264
5265         if(ifx) ifx->generated = 1;
5266         return;
5267
5268       }
5269       size--;
5270
5271       if(size == 0) {
5272         //i = (lit >> (size*8)) & 0xff;
5273         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5274         
5275         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5276
5277         i = ((0-lit) & 0xff);
5278         if(sign) {
5279           if( i == 0x81) { 
5280             /* lit is 0x7f, all signed chars are less than
5281              * this except for 0x7f itself */
5282             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5283             genSkipz2(&rFalseIfx,0);
5284           } else {
5285             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5286             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5287             genSkipc(&rFalseIfx);
5288           }
5289
5290         } else {
5291           if(lit == 1) {
5292             genSkipz2(&rFalseIfx,1);
5293           } else {
5294             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5295             genSkipc(&rFalseIfx);
5296           }
5297         }
5298
5299         if(ifx) ifx->generated = 1;
5300         return;
5301       }
5302
5303       /* chars are out of the way. now do ints and longs */
5304
5305
5306       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5307         
5308       /* special cases */
5309
5310       if(sign) {
5311
5312         if(lit == 0) {
5313           genSkipCond(&rFalseIfx,left,size,7);
5314           if(ifx) ifx->generated = 1;
5315           return;
5316         }
5317
5318         if(lit <0x100) {
5319           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5320
5321           //rFalseIfx.condition ^= 1;
5322           //genSkipCond(&rFalseIfx,left,size,7);
5323           //rFalseIfx.condition ^= 1;
5324
5325           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5326           if(rFalseIfx.condition)
5327             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5328           else
5329             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5330
5331           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5332           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5333           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5334
5335           while(size > 1)
5336             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5337
5338           if(rFalseIfx.condition) {
5339             emitSKPZ;
5340             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5341
5342           } else {
5343             emitSKPNZ;
5344           }
5345
5346           genSkipc(&rFalseIfx);
5347           pic16_emitpLabel(truelbl->key);
5348           if(ifx) ifx->generated = 1;
5349           return;
5350
5351         }
5352
5353         if(size == 1) {
5354
5355           if( (lit & 0xff) == 0) {
5356             /* lower byte is zero */
5357             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5358             i = ((lit >> 8) & 0xff) ^0x80;
5359             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5360             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5361             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5362             genSkipc(&rFalseIfx);
5363
5364
5365             if(ifx) ifx->generated = 1;
5366             return;
5367
5368           }
5369         } else {
5370           /* Special cases for signed longs */
5371           if( (lit & 0xffffff) == 0) {
5372             /* lower byte is zero */
5373             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5374             i = ((lit >> 8*3) & 0xff) ^0x80;
5375             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5376             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5377             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5378             genSkipc(&rFalseIfx);
5379
5380
5381             if(ifx) ifx->generated = 1;
5382             return;
5383
5384           }
5385
5386         }
5387
5388
5389         if(lit & (0x80 << (size*8))) {
5390           /* lit is negative */
5391           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5392
5393           //genSkipCond(&rFalseIfx,left,size,7);
5394
5395           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5396
5397           if(rFalseIfx.condition)
5398             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5399           else
5400             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5401
5402
5403         } else {
5404           /* lit is positive */
5405           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5406           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5407           if(rFalseIfx.condition)
5408             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5409           else
5410             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5411
5412         }
5413
5414         /*
5415           This works, but is only good for ints.
5416           It also requires a "known zero" register.
5417           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5418           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5419           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5420           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5421           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5422           genSkipc(&rFalseIfx);
5423
5424           pic16_emitpLabel(truelbl->key);
5425           if(ifx) ifx->generated = 1;
5426           return;
5427         **/
5428           
5429         /* There are no more special cases, so perform a general compare */
5430   
5431         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5432         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5433
5434         while(size--) {
5435
5436           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5437           emitSKPNZ;
5438           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5439         }
5440         //rFalseIfx.condition ^= 1;
5441         genSkipc(&rFalseIfx);
5442
5443         pic16_emitpLabel(truelbl->key);
5444
5445         if(ifx) ifx->generated = 1;
5446         return;
5447
5448
5449       }
5450
5451
5452       /* sign is out of the way. So now do an unsigned compare */
5453       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5454
5455
5456       /* General case - compare to an unsigned literal on the right.*/
5457
5458       i = (lit >> (size*8)) & 0xff;
5459       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5460       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5461       while(size--) {
5462         i = (lit >> (size*8)) & 0xff;
5463
5464         if(i) {
5465           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5466           emitSKPNZ;
5467           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5468         } else {
5469           /* this byte of the lit is zero, 
5470            *if it's not the last then OR in the variable */
5471           if(size)
5472             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5473         }
5474       }
5475
5476
5477       pic16_emitpLabel(lbl->key);
5478 //      pic16_emitpLabel(truelbl->key);
5479       //if(emitFinalCheck)
5480       genSkipc(&rFalseIfx);
5481       if(sign)
5482         pic16_emitpLabel(truelbl->key);
5483
5484       if(ifx) ifx->generated = 1;
5485       return;
5486
5487
5488     }
5489 #endif  // _swapp
5490
5491     if(AOP_TYPE(left) == AOP_LIT) {
5492       //symbol *lbl = newiTempLabel(NULL);
5493
5494       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5495
5496
5497       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5498
5499       /* Special cases */
5500       if((lit == 0) && (sign == 0)){
5501
5502         size--;
5503         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5504         while(size) 
5505           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5506
5507         genSkipz2(&rFalseIfx,0);
5508         if(ifx) ifx->generated = 1;
5509         return;
5510       }
5511
5512       if(size==1) {
5513         /* Special cases */
5514         lit &= 0xff;
5515         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5516           /* degenerate compare can never be true */
5517           if(rFalseIfx.condition == 0)
5518             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5519
5520           if(ifx) ifx->generated = 1;
5521           return;
5522         }
5523
5524         if(sign) {
5525           /* signed comparisons to a literal byte */
5526
5527           int lp1 = (lit+1) & 0xff;
5528
5529           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5530           switch (lp1) {
5531           case 0:
5532             rFalseIfx.condition ^= 1;
5533             genSkipCond(&rFalseIfx,right,0,7);
5534             break;
5535           case 0x7f:
5536             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5537             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5538             genSkipz2(&rFalseIfx,1);
5539             break;
5540           default:
5541             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5542             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5543             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5544             rFalseIfx.condition ^= 1;
5545             genSkipc(&rFalseIfx);
5546             break;
5547           }
5548         } else {
5549           /* unsigned comparisons to a literal byte */
5550
5551           switch(lit & 0xff ) {
5552           case 0:
5553             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5554             genSkipz2(&rFalseIfx,0);
5555             break;
5556           case 0x7f:
5557             rFalseIfx.condition ^= 1;
5558             genSkipCond(&rFalseIfx,right,0,7);
5559             break;
5560
5561           default:
5562             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5563             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5564             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5565             rFalseIfx.condition ^= 1;
5566             if (AOP_TYPE(result) == AOP_CRY)
5567               genSkipc(&rFalseIfx);
5568             else {
5569               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5570               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5571             }         
5572             break;
5573           }
5574         }
5575
5576         if(ifx) ifx->generated = 1;
5577         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5578                 goto check_carry;
5579         return;
5580
5581       } else {
5582
5583         /* Size is greater than 1 */
5584
5585         if(sign) {
5586           int lp1 = lit+1;
5587
5588           size--;
5589
5590           if(lp1 == 0) {
5591             /* this means lit = 0xffffffff, or -1 */
5592
5593
5594             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5595             rFalseIfx.condition ^= 1;
5596             genSkipCond(&rFalseIfx,right,size,7);
5597             if(ifx) ifx->generated = 1;
5598
5599             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5600               goto check_carry;
5601
5602             return;
5603           }
5604
5605           if(lit == 0) {
5606             int s = size;
5607
5608             if(rFalseIfx.condition) {
5609               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5610               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5611             }
5612
5613             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5614             while(size--)
5615               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5616
5617
5618             emitSKPZ;
5619             if(rFalseIfx.condition) {
5620               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5621               pic16_emitpLabel(truelbl->key);
5622             }else {
5623               rFalseIfx.condition ^= 1;
5624               genSkipCond(&rFalseIfx,right,s,7);
5625             }
5626
5627             if(ifx) ifx->generated = 1;
5628
5629             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5630               goto check_carry;
5631
5632             return;
5633           }
5634
5635           if((size == 1) &&  (0 == (lp1&0xff))) {
5636             /* lower byte of signed word is zero */
5637             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5638             i = ((lp1 >> 8) & 0xff) ^0x80;
5639             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5640             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5641             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5642
5643             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5644               emitTOGC;
5645               if(ifx) ifx->generated = 1;
5646               goto check_carry;
5647             } else {
5648               rFalseIfx.condition ^= 1;
5649               genSkipc(&rFalseIfx);
5650               if(ifx) ifx->generated = 1;
5651             }
5652
5653             return;
5654           }
5655
5656           if(lit & (0x80 << (size*8))) {
5657             /* Lit is less than zero */
5658             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5659             //rFalseIfx.condition ^= 1;
5660             //genSkipCond(&rFalseIfx,left,size,7);
5661             //rFalseIfx.condition ^= 1;
5662             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5663             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5664
5665             if(rFalseIfx.condition)
5666               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5667             else
5668               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5669
5670
5671           } else {
5672             /* Lit is greater than or equal to zero */
5673             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5674             //rFalseIfx.condition ^= 1;
5675             //genSkipCond(&rFalseIfx,right,size,7);
5676             //rFalseIfx.condition ^= 1;
5677
5678             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5679             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5680
5681             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5682             if(rFalseIfx.condition)
5683               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5684             else
5685               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5686
5687           }
5688
5689           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5690           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5691
5692           while(size--) {
5693
5694             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5695             emitSKPNZ;
5696             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5697           }
5698           rFalseIfx.condition ^= 1;
5699           //rFalseIfx.condition = 1;
5700           genSkipc(&rFalseIfx);
5701
5702           pic16_emitpLabel(truelbl->key);
5703
5704           if(ifx) ifx->generated = 1;
5705
5706
5707           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5708             goto check_carry;
5709
5710           return;
5711           // end of if (sign)
5712         } else {
5713
5714           /* compare word or long to an unsigned literal on the right.*/
5715
5716
5717           size--;
5718           if(lit < 0xff) {
5719             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5720             switch (lit) {
5721             case 0:
5722               break; /* handled above */
5723 /*
5724             case 0xff:
5725               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5726               while(size--)
5727                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5728               genSkipz2(&rFalseIfx,0);
5729               break;
5730 */
5731             default:
5732               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5733               while(--size)
5734                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5735
5736               emitSKPZ;
5737               if(rFalseIfx.condition)
5738                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5739               else
5740                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5741
5742
5743               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5744               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5745
5746               rFalseIfx.condition ^= 1;
5747               genSkipc(&rFalseIfx);
5748             }
5749
5750             pic16_emitpLabel(truelbl->key);
5751
5752             if(ifx) ifx->generated = 1;
5753
5754             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5755               goto check_carry;
5756
5757             return;
5758           }
5759
5760
5761           lit++;
5762           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5763           i = (lit >> (size*8)) & 0xff;
5764
5765           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5766           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5767
5768           while(size--) {
5769             i = (lit >> (size*8)) & 0xff;
5770
5771             if(i) {
5772               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5773               emitSKPNZ;
5774               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5775             } else {
5776               /* this byte of the lit is zero, 
5777                * if it's not the last then OR in the variable */
5778               if(size)
5779                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5780             }
5781           }
5782
5783
5784           pic16_emitpLabel(lbl->key);
5785
5786           rFalseIfx.condition ^= 1;
5787
5788           genSkipc(&rFalseIfx);
5789         }
5790
5791         if(sign)
5792           pic16_emitpLabel(truelbl->key);
5793         if(ifx) ifx->generated = 1;
5794
5795             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5796               goto check_carry;
5797
5798         return;
5799       }
5800     }
5801     /* Compare two variables */
5802
5803     DEBUGpic16_emitcode(";sign","%d",sign);
5804
5805     size--;
5806     if(sign) {
5807       /* Sigh. thus sucks... */
5808       if(size) {
5809         pCodeOp *pctemp;
5810         
5811         pctemp = pic16_popGetTempReg(1);
5812         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5813         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5814         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5815         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5816         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5817         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5818         pic16_popReleaseTempReg(pctemp, 1);
5819       } else {
5820         /* Signed char comparison */
5821         /* Special thanks to Nikolai Golovchenko for this snippet */
5822         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5823         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5824         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5825         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5826         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5827         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5828
5829         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5830         genSkipc(&rFalseIfx);
5831           
5832         if(ifx) ifx->generated = 1;
5833
5834             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5835               goto check_carry;
5836
5837         return;
5838       }
5839
5840     } else {
5841
5842       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5843       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5844     }
5845
5846
5847     /* The rest of the bytes of a multi-byte compare */
5848     while (size) {
5849
5850       emitSKPZ;
5851       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5852       size--;
5853
5854       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5855       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5856
5857
5858     }
5859
5860     pic16_emitpLabel(lbl->key);
5861
5862     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5863     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5864         (AOP_TYPE(result) == AOP_REG)) {
5865       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5866       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5867     } else {
5868       genSkipc(&rFalseIfx);
5869     }         
5870     //genSkipc(&rFalseIfx);
5871     if(ifx) ifx->generated = 1;
5872
5873
5874             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5875               goto check_carry;
5876
5877     return;
5878
5879   }
5880
5881 check_carry:
5882   if ((AOP_TYPE(result) != AOP_CRY) 
5883         && AOP_SIZE(result)) {
5884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5885
5886     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5887
5888     pic16_outBitC(result);
5889   } else {
5890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5891     /* if the result is used in the next
5892        ifx conditional branch then generate
5893        code a little differently */
5894     if (ifx )
5895       genIfxJump (ifx,"c");
5896     else
5897       pic16_outBitC(result);
5898     /* leave the result in acc */
5899   }
5900
5901 }
5902
5903 #elif 0 /* VR version of genCmp() */    /* } else { */
5904
5905 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5906 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5907         operand *result, int offset, int invert_op)
5908 {
5909   /* add code here */
5910   
5911   /* check condition, > or < ?? */
5912   if(rIfx->condition != 0)invert_op ^= 1;
5913   
5914   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5915
5916   if(!ifx)invert_op ^= 1;
5917
5918   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5919       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5920   
5921   /* do selection */
5922   if(!invert_op)return POC_CPFSGT;
5923   else return POC_CPFSLT;
5924 }
5925
5926 static int compareAopfirstpass=1;
5927
5928 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5929             operand *oper, int offset, operand *result,
5930             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5931             symbol *tlbl)
5932 {
5933   int op;
5934   symbol *truelbl;
5935
5936   /* invert if there is a result to be loaded, in order to fit,
5937    * SETC/CLRC sequence */
5938   if(AOP_SIZE(result))invert_op ^= 1;
5939
5940 //  if(sign && !offset)invert_op ^= 1;
5941   
5942 //  if(sign)invert_op ^= 1;
5943   
5944   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5945
5946   if(AOP_SIZE(result) && compareAopfirstpass) {
5947     if(!ifx) {
5948       if(pcop2)
5949         pic16_emitpcode(POC_SETF, pcop2);
5950       else
5951         emitSETC;
5952     } else {
5953       if(pcop2)
5954         pic16_emitpcode(POC_CLRF, pcop2);
5955       else
5956         emitCLRC;
5957     }
5958   }
5959
5960   compareAopfirstpass = 0;
5961
5962       /* there is a bug when comparing operands with size > 1,
5963        * because higher bytes can be equal and test should be performed
5964        * to the next lower byte, current algorithm, considers operands
5965        * inequal in these cases! -- VR 20041107 */
5966
5967     
5968   if(pcop)
5969     pic16_emitpcode(op, pcop);
5970   else
5971     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5972
5973
5974   if((!sign || !offset) && AOP_SIZE(result)) {
5975     if(!ifx) {
5976       if(pcop2)
5977         pic16_emitpcode(POC_CLRF, pcop2);
5978         else
5979         emitCLRC;
5980     } else {
5981       if(pcop2)
5982         pic16_emitpcode(POC_SETF, pcop2);
5983       else
5984         emitSETC;
5985     }
5986     
5987     /* don't emit final branch (offset == 0) */
5988     if(offset) {
5989
5990       if(pcop2)
5991         pic16_emitpcode(POC_RRCF, pcop2);
5992
5993       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5994     }
5995   } else {
5996     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5997       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5998             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5999
6000       truelbl = newiTempLabel( NULL );
6001       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6002       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6003         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6004       else
6005         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6006       pic16_emitpLabel(truelbl->key);
6007     } else {
6008       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6009     }
6010   }
6011 }
6012
6013 static void genCmp (operand *left, operand *right,
6014                     operand *result, iCode *ifx, int sign)
6015 {
6016   int size, cmpop=1;
6017   long lit = 0L;
6018   resolvedIfx rFalseIfx;
6019   symbol *falselbl, *tlbl;
6020
6021     FENTRY;
6022     
6023     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6024
6025     resolveIfx(&rFalseIfx, ifx);
6026     size = max(AOP_SIZE(left), AOP_SIZE(right));
6027     
6028     /* if left & right are bit variables */
6029     if(AOP_TYPE(left) == AOP_CRY
6030       && AOP_TYPE(right) == AOP_CRY ) {
6031
6032         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6033         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6034         
6035         werror(W_POSSBUG2, __FILE__, __LINE__);
6036         exit(-1);
6037     }
6038     
6039     /* if literal is on the right then swap with left */
6040     if((AOP_TYPE(right) == AOP_LIT)) {
6041       operand *tmp = right ;
6042 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6043
6044         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6045
6046 //      lit = (lit - 1) & mask;
6047         right = left;
6048         left = tmp;
6049         rFalseIfx.condition ^= 1;               /* reverse compare */
6050     } else
6051     if ((AOP_TYPE(left) == AOP_LIT)) {
6052       /* float compares are handled by support functions */
6053       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6054     }
6055
6056     /* actual comparing algorithm */
6057 //    size = AOP_SIZE( right );
6058
6059     falselbl = newiTempLabel( NULL );
6060     if(AOP_TYPE(left) == AOP_LIT) {
6061       /* compare to literal */
6062       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6063       
6064       if(sign) {
6065         pCodeOp *pct, *pct2;
6066         symbol *tlbl1;
6067
6068         /* signed compare */
6069         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6070
6071         pct = pic16_popCopyReg(&pic16_pc_prodl);
6072         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6073         tlbl = newiTempLabel( NULL );
6074         
6075         /* first compare signs:
6076          *  a. if both are positive, compare just like unsigned
6077          *  b. if both are negative, invert cmpop, compare just like unsigned
6078          *  c. if different signs, determine the result directly */
6079
6080         size--;
6081
6082 #if 1
6083         /* { */
6084         tlbl1 = newiTempLabel( NULL );
6085 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6086
6087         if(lit > 0) {
6088
6089           /* literal is zero or positive:
6090            *  a. if carry is zero, too, continue compare,
6091            *  b. if carry is set, then continue depending on cmpop ^ condition:
6092            *    1. '<' return false (literal < variable),
6093            *    2. '>' return true (literal > variable) */
6094 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6095           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6096           
6097           
6098           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6099           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6100         } else 
6101         if(lit < 0) {
6102           
6103           /* literal is negative:
6104            *  a. if carry is set, too, continue compare,
6105            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6106            *    1. '<' return true (literal < variable),
6107            *    2. '>' return false (literal > variable) */
6108 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6109           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6110           
6111           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6112           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6113         }
6114 #if 1
6115         else {
6116           /* lit == 0 */
6117           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6118           
6119           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6120           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6121         }
6122 #endif
6123         
6124         
6125         pic16_emitpLabel( tlbl1->key );
6126 #endif  /* } */
6127
6128         compareAopfirstpass=1;
6129 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6130 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6131 //        pic16_emitpcode(POC_MOVWF, pct);
6132
6133 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6134         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6135 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6136         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6137
6138         /* generic case */        
6139           while( size-- ) {
6140 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6141 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6142 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6143 //            pic16_emitpcode(POC_MOVWF, pct);
6144
6145 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6146             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6147             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6148 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6149 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6150           }
6151 //        }
6152         
6153         if(ifx)ifx->generated = 1;
6154
6155         if(AOP_SIZE(result)) {
6156           pic16_emitpLabel(tlbl->key);
6157           pic16_emitpLabel(falselbl->key);
6158           pic16_outBitOp( result, pct2 );
6159         } else {
6160           pic16_emitpLabel(tlbl->key);
6161         }
6162       } else {
6163
6164
6165         /* unsigned compare */      
6166         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6167     
6168         compareAopfirstpass=1;
6169         while(size--) {
6170           
6171           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6172           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6173
6174         }
6175
6176         if(ifx)ifx->generated = 1;
6177
6178
6179         if(AOP_SIZE(result)) {
6180           pic16_emitpLabel(falselbl->key);
6181           pic16_outBitC( result );
6182         }
6183
6184       }
6185     } else {
6186       /* compare registers */
6187       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6188
6189
6190       if(sign) {
6191         pCodeOp *pct, *pct2;
6192         
6193         /* signed compare */
6194         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6195
6196         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6197         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6198         tlbl = newiTempLabel( NULL );
6199         
6200         compareAopfirstpass=1;
6201
6202         size--;
6203         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6204 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6206         pic16_emitpcode(POC_MOVWF, pct);
6207
6208         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6209 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6210         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6211
6212         /* WREG already holds left + 0x80 */
6213         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6214         
6215         while( size-- ) {
6216           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6217 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219           pic16_emitpcode(POC_MOVWF, pct);
6220                 
6221           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6222 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6223           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6224
6225           /* WREG already holds left + 0x80 */
6226           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6227 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6228         }
6229         
6230         if(ifx)ifx->generated = 1;
6231
6232         if(AOP_SIZE(result)) {
6233           pic16_emitpLabel(tlbl->key);
6234           pic16_emitpLabel(falselbl->key);
6235           pic16_outBitOp( result, pct2 );
6236         } else {
6237           pic16_emitpLabel(tlbl->key);
6238         }
6239
6240       } else {
6241         /* unsigned compare */      
6242         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6243
6244         compareAopfirstpass=1;
6245         while(size--) {
6246           
6247           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6248           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6249
6250         }
6251
6252         if(ifx)ifx->generated = 1;
6253         if(AOP_SIZE(result)) {
6254
6255           pic16_emitpLabel(falselbl->key);
6256           pic16_outBitC( result );
6257         }
6258
6259       }
6260     }
6261 }
6262
6263 #endif  /* } */
6264
6265
6266
6267 /*-----------------------------------------------------------------*/
6268 /* genCmpGt :- greater than comparison                             */
6269 /*-----------------------------------------------------------------*/
6270 static void genCmpGt (iCode *ic, iCode *ifx)
6271 {
6272   operand *left, *right, *result;
6273   sym_link *letype , *retype;
6274   int sign ;
6275
6276     FENTRY;
6277     
6278     left = IC_LEFT(ic);
6279     right= IC_RIGHT(ic);
6280     result = IC_RESULT(ic);
6281
6282     letype = getSpec(operandType(left));
6283     retype =getSpec(operandType(right));
6284     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6285     /* assign the amsops */
6286     pic16_aopOp (left,ic,FALSE);
6287     pic16_aopOp (right,ic,FALSE);
6288     pic16_aopOp (result,ic,TRUE);
6289
6290     genCmp(right, left, result, ifx, sign);
6291
6292     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6293     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6294     pic16_freeAsmop(result,NULL,ic,TRUE); 
6295 }
6296
6297 /*-----------------------------------------------------------------*/
6298 /* genCmpLt - less than comparisons                                */
6299 /*-----------------------------------------------------------------*/
6300 static void genCmpLt (iCode *ic, iCode *ifx)
6301 {
6302   operand *left, *right, *result;
6303   sym_link *letype , *retype;
6304   int sign ;
6305
6306     FENTRY;
6307
6308     left = IC_LEFT(ic);
6309     right= IC_RIGHT(ic);
6310     result = IC_RESULT(ic);
6311
6312     letype = getSpec(operandType(left));
6313     retype =getSpec(operandType(right));
6314     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6315
6316     /* assign the amsops */
6317     pic16_aopOp (left,ic,FALSE);
6318     pic16_aopOp (right,ic,FALSE);
6319     pic16_aopOp (result,ic,TRUE);
6320
6321     genCmp(left, right, result, ifx, sign);
6322
6323     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6324     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6325     pic16_freeAsmop(result,NULL,ic,TRUE); 
6326 }
6327
6328 #if 0
6329 // not needed ATM
6330 // FIXME reenable literal optimisation when the pic16 port is stable
6331
6332 /*-----------------------------------------------------------------*/
6333 /* genc16bit2lit - compare a 16 bit value to a literal             */
6334 /*-----------------------------------------------------------------*/
6335 static void genc16bit2lit(operand *op, int lit, int offset)
6336 {
6337   int i;
6338
6339   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6340   if( (lit&0xff) == 0) 
6341     i=1;
6342   else
6343     i=0;
6344
6345   switch( BYTEofLONG(lit,i)) { 
6346   case 0:
6347     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6348     break;
6349   case 1:
6350     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6351     break;
6352   case 0xff:
6353     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6354     break;
6355   default:
6356     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6357     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6358   }
6359
6360   i ^= 1;
6361
6362   switch( BYTEofLONG(lit,i)) { 
6363   case 0:
6364     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6365     break;
6366   case 1:
6367     emitSKPNZ;
6368     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6369     break;
6370   case 0xff:
6371     emitSKPNZ;
6372     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6373     break;
6374   default:
6375     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6376     emitSKPNZ;
6377     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6378
6379   }
6380
6381 }
6382 #endif
6383
6384 #if 0
6385 // not needed ATM
6386 /*-----------------------------------------------------------------*/
6387 /* gencjneshort - compare and jump if not equal                    */
6388 /*-----------------------------------------------------------------*/
6389 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6390 {
6391   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6392   int offset = 0;
6393   int res_offset = 0;  /* the result may be a different size then left or right */
6394   int res_size = AOP_SIZE(result);
6395   resolvedIfx rIfx;
6396   symbol *lbl, *lbl_done;
6397
6398   unsigned long lit = 0L;
6399   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6400
6401   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6402   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6403   if(result)
6404     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6405   resolveIfx(&rIfx,ifx);
6406   lbl =  newiTempLabel(NULL);
6407   lbl_done =  newiTempLabel(NULL);
6408
6409
6410   /* if the left side is a literal or 
6411      if the right is in a pointer register and left 
6412      is not */
6413   if ((AOP_TYPE(left) == AOP_LIT) || 
6414       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6415     operand *t = right;
6416     right = left;
6417     left = t;
6418   }
6419   if(AOP_TYPE(right) == AOP_LIT)
6420     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6421
6422   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6423     preserve_result = 1;
6424
6425   if(result && !preserve_result)
6426     {
6427       int i;
6428       for(i = 0; i < AOP_SIZE(result); i++)
6429         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6430     }
6431
6432
6433   /* if the right side is a literal then anything goes */
6434   if (AOP_TYPE(right) == AOP_LIT &&
6435       AOP_TYPE(left) != AOP_DIR ) {
6436     switch(size) {
6437     case 2:
6438       genc16bit2lit(left, lit, 0);
6439       emitSKPZ;
6440       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6441       break;
6442     default:
6443       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6444       while (size--) {
6445         if(lit & 0xff) {
6446           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6447           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6448         } else {
6449           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6450         }
6451
6452         emitSKPZ;
6453         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6454         offset++;
6455         if(res_offset < res_size-1)
6456           res_offset++;
6457         lit >>= 8;
6458       }
6459       break;
6460     }
6461   }
6462
6463   /* if the right side is in a register or in direct space or
6464      if the left is a pointer register & right is not */    
6465   else if (AOP_TYPE(right) == AOP_REG ||
6466            AOP_TYPE(right) == AOP_DIR || 
6467            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6468            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6469     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6470     int lbl_key = lbl->key;
6471
6472     if(result) {
6473       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6474       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6475     }else {
6476       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6477       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6478               __FUNCTION__,__LINE__);
6479       return;
6480     }
6481    
6482 /*     switch(size) { */
6483 /*     case 2: */
6484 /*       genc16bit2lit(left, lit, 0); */
6485 /*       emitSKPNZ; */
6486 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6487 /*       break; */
6488 /*     default: */
6489     while (size--) {
6490       int emit_skip=1;
6491       if((AOP_TYPE(left) == AOP_DIR) && 
6492          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6493
6494         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6495         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6496
6497       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6498             
6499         switch (lit & 0xff) {
6500         case 0:
6501           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6502           break;
6503         case 1:
6504           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6505           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6506           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6507           emit_skip=0;
6508           break;
6509         case 0xff:
6510           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6511           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6514           emit_skip=0;
6515           break;
6516         default:
6517           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6518           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6519         }
6520         lit >>= 8;
6521
6522       } else {
6523         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6524       }
6525       if(emit_skip) {
6526         if(AOP_TYPE(result) == AOP_CRY) {
6527           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6528           if(rIfx.condition)
6529             emitSKPNZ;
6530           else
6531             emitSKPZ;
6532           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6533         } else {
6534           /* fix me. probably need to check result size too */
6535           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6536           if(rIfx.condition)
6537             emitSKPZ;
6538           else
6539             emitSKPNZ;
6540           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6541           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6542         }
6543         if(ifx)
6544           ifx->generated=1;
6545       }
6546       emit_skip++;
6547       offset++;
6548       if(res_offset < res_size-1)
6549         res_offset++;
6550     }
6551 /*       break; */
6552 /*     } */
6553   } else if(AOP_TYPE(right) == AOP_REG &&
6554             AOP_TYPE(left) != AOP_DIR){
6555
6556     while(size--) {
6557       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6558       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6559       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6560       if(rIfx.condition)
6561         emitSKPNZ;
6562       else
6563         emitSKPZ;
6564       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6565       offset++;
6566       if(res_offset < res_size-1)
6567         res_offset++;
6568     }
6569       
6570   }else{
6571     /* right is a pointer reg need both a & b */
6572     while(size--) {
6573       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6574       if(strcmp(l,"b"))
6575         pic16_emitcode("mov","b,%s",l);
6576       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6577       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6578       offset++;
6579     }
6580   }
6581
6582   if(result && preserve_result)
6583     {
6584       int i;
6585       for(i = 0; i < AOP_SIZE(result); i++)
6586         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6587     }
6588
6589   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6590
6591   if(result && preserve_result)
6592     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6593
6594   if(!rIfx.condition)
6595     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6596
6597   pic16_emitpLabel(lbl->key);
6598
6599   if(result && preserve_result)
6600     {
6601       int i;
6602       for(i = 0; i < AOP_SIZE(result); i++)
6603         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6604
6605       pic16_emitpLabel(lbl_done->key);
6606    }
6607
6608   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6609
6610   if(ifx)
6611     ifx->generated = 1;
6612 }
6613 #endif
6614
6615 #if 0
6616 /*-----------------------------------------------------------------*/
6617 /* gencjne - compare and jump if not equal                         */
6618 /*-----------------------------------------------------------------*/
6619 static void gencjne(operand *left, operand *right, iCode *ifx)
6620 {
6621     symbol *tlbl  = newiTempLabel(NULL);
6622
6623     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6624     gencjneshort(left, right, lbl);
6625
6626     pic16_emitcode("mov","a,%s",one);
6627     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6628     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6629     pic16_emitcode("clr","a");
6630     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6631
6632     pic16_emitpLabel(lbl->key);
6633     pic16_emitpLabel(tlbl->key);
6634
6635 }
6636 #endif
6637
6638
6639 /*-----------------------------------------------------------------*/
6640 /* is_LitOp - check if operand has to be treated as literal        */
6641 /*-----------------------------------------------------------------*/
6642 static bool is_LitOp(operand *op)
6643 {
6644   return ((AOP_TYPE(op) == AOP_LIT)
6645       || ( (AOP_TYPE(op) == AOP_PCODE)
6646           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6647               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6648 }
6649
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitAOp - check if operand has to be treated as literal        */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitAOp(asmop *aop)
6654 {
6655   return ((aop->type == AOP_LIT)
6656       || ( (aop->type == AOP_PCODE)
6657           && ( (aop->aopu.pcop->type == PO_LITERAL)
6658               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6659 }
6660
6661
6662
6663 /*-----------------------------------------------------------------*/
6664 /* genCmpEq - generates code for equal to                          */
6665 /*-----------------------------------------------------------------*/
6666 static void genCmpEq (iCode *ic, iCode *ifx)
6667 {
6668   operand *left, *right, *result;
6669   symbol *falselbl = newiTempLabel(NULL);
6670   symbol *donelbl = newiTempLabel(NULL);
6671
6672   int preserve_result = 0;
6673   int generate_result = 0;
6674   int i=0;
6675   unsigned long lit = -1;
6676
6677   FENTRY;
6678   
6679   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6680   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6681   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6682  
6683   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6684
6685   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6686     {
6687       werror(W_POSSBUG2, __FILE__, __LINE__);
6688       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6689       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6690       goto release;
6691     }
6692
6693   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6694     {
6695       operand *tmp = right ;
6696       right = left;
6697       left = tmp;
6698     }
6699
6700   if (AOP_TYPE(right) == AOP_LIT) {
6701     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6702   }
6703
6704   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6705     preserve_result = 1;
6706
6707   if(result && AOP_SIZE(result))
6708     generate_result = 1;
6709
6710   if(generate_result && !preserve_result)
6711     {
6712       for(i = 0; i < AOP_SIZE(result); i++)
6713         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6714     }
6715
6716   for(i=0; i < AOP_SIZE(left); i++)
6717     {
6718       if(AOP_TYPE(left) != AOP_ACC)
6719         {
6720           if(is_LitOp(left))
6721             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6722           else
6723             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6724         }
6725       if(is_LitOp(right)) {
6726         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6727           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6728         }
6729       } else
6730         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6731
6732       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6733     }
6734
6735   // result == true
6736
6737   if(generate_result && preserve_result)
6738     {
6739       for(i = 0; i < AOP_SIZE(result); i++)
6740         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6741     }
6742
6743   if(generate_result)
6744     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6745
6746   if(generate_result && preserve_result)
6747     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6748
6749   if(ifx && IC_TRUE(ifx))
6750     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6751
6752   if(ifx && IC_FALSE(ifx))
6753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6754
6755   pic16_emitpLabel(falselbl->key);
6756
6757   // result == false
6758
6759   if(ifx && IC_FALSE(ifx))
6760     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6761
6762   if(generate_result && preserve_result)
6763     {
6764       for(i = 0; i < AOP_SIZE(result); i++)
6765         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6766     }
6767
6768   pic16_emitpLabel(donelbl->key);
6769
6770   if(ifx)
6771     ifx->generated = 1;
6772
6773 release:
6774   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6775   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6776   pic16_freeAsmop(result,NULL,ic,TRUE);
6777
6778 }
6779
6780
6781 #if 0
6782 // old version kept for reference
6783
6784 /*-----------------------------------------------------------------*/
6785 /* genCmpEq - generates code for equal to                          */
6786 /*-----------------------------------------------------------------*/
6787 static void genCmpEq (iCode *ic, iCode *ifx)
6788 {
6789     operand *left, *right, *result;
6790     unsigned long lit = 0L;
6791     int size,offset=0;
6792     symbol *falselbl  = newiTempLabel(NULL);
6793
6794
6795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6796
6797     if(ifx)
6798       DEBUGpic16_emitcode ("; ifx is non-null","");
6799     else
6800       DEBUGpic16_emitcode ("; ifx is null","");
6801
6802     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6803     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6804     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6805
6806     size = max(AOP_SIZE(left),AOP_SIZE(right));
6807
6808     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6809
6810     /* if literal, literal on the right or 
6811     if the right is in a pointer register and left 
6812     is not */
6813     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6814         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6815       operand *tmp = right ;
6816       right = left;
6817       left = tmp;
6818     }
6819
6820
6821     if(ifx && !AOP_SIZE(result)){
6822         symbol *tlbl;
6823         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6824         /* if they are both bit variables */
6825         if (AOP_TYPE(left) == AOP_CRY &&
6826             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6827                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6828             if(AOP_TYPE(right) == AOP_LIT){
6829                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6830                 if(lit == 0L){
6831                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832                     pic16_emitcode("cpl","c");
6833                 } else if(lit == 1L) {
6834                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6835                 } else {
6836                     pic16_emitcode("clr","c");
6837                 }
6838                 /* AOP_TYPE(right) == AOP_CRY */
6839             } else {
6840                 symbol *lbl = newiTempLabel(NULL);
6841                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6843                 pic16_emitcode("cpl","c");
6844                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6845             }
6846             /* if true label then we jump if condition
6847             supplied is true */
6848             tlbl = newiTempLabel(NULL);
6849             if ( IC_TRUE(ifx) ) {
6850                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6851                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6852             } else {
6853                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6854                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6855             }
6856             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6857
6858                 {
6859                 /* left and right are both bit variables, result is carry */
6860                         resolvedIfx rIfx;
6861               
6862                         resolveIfx(&rIfx,ifx);
6863
6864                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6865                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6866                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6867                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6868                         genSkipz2(&rIfx,0);
6869                 }
6870         } else {
6871
6872                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6873
6874                         /* They're not both bit variables. Is the right a literal? */
6875                         if(AOP_TYPE(right) == AOP_LIT) {
6876                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6877             
6878                         switch(size) {
6879
6880                                 case 1:
6881                                         switch(lit & 0xff) {
6882                                                 case 1:
6883                                                                 if ( IC_TRUE(ifx) ) {
6884                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6885                                                                         emitSKPNZ;
6886                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6887                                                                 } else {
6888                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6889                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6890                                                                 }
6891                                                                 break;
6892                                                 case 0xff:
6893                                                                 if ( IC_TRUE(ifx) ) {
6894                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6895                                                                         emitSKPNZ;
6896                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6897                                                                 } else {
6898                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6899                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6900                                                                 }
6901                                                                 break;
6902                                                 default:
6903                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6904                                                                 if(lit)
6905                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6906                                                                 genSkip(ifx,'z');
6907                                         } // switch lit
6908
6909
6910                                         /* end of size == 1 */
6911                                         break;
6912               
6913                                 case 2:
6914                                         genc16bit2lit(left,lit,offset);
6915                                         genSkip(ifx,'z');
6916                                         break;
6917                                         /* end of size == 2 */
6918
6919                                 default:
6920                                         /* size is 4 */
6921                                         if(lit==0) {
6922                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6923                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6924                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6925                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6926                                                 genSkip(ifx,'z');
6927                                         } else {
6928                                                 /* search for patterns that can be optimized */
6929
6930                                                 genc16bit2lit(left,lit,0);
6931                                                 lit >>= 16;
6932                                                 if(lit) {
6933                                                                 if(IC_TRUE(ifx))
6934                                                                 emitSKPZ; // if hi word unequal
6935                                                                 else
6936                                                                 emitSKPNZ; // if hi word equal
6937                                                                 // fail early
6938                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6939                                                         genc16bit2lit(left,lit,2);
6940                                                         genSkip(ifx,'z');
6941                                                 } else {
6942                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6943                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6944                                                         genSkip(ifx,'z');
6945                                                 }
6946                                         }
6947                                                 pic16_emitpLabel(falselbl->key);
6948                                                 break;
6949
6950                         } // switch size
6951           
6952                         ifx->generated = 1;
6953                         goto release ;
6954             
6955
6956           } else if(AOP_TYPE(right) == AOP_CRY ) {
6957             /* we know the left is not a bit, but that the right is */
6958             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6959             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6960                       pic16_popGet(AOP(right),offset));
6961             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6962
6963             /* if the two are equal, then W will be 0 and the Z bit is set
6964              * we could test Z now, or go ahead and check the high order bytes if
6965              * the variable we're comparing is larger than a byte. */
6966
6967             while(--size)
6968               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6969
6970             if ( IC_TRUE(ifx) ) {
6971               emitSKPNZ;
6972               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6973               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6974             } else {
6975               emitSKPZ;
6976               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6977               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6978             }
6979
6980           } else {
6981             /* They're both variables that are larger than bits */
6982             int s = size;
6983
6984             tlbl = newiTempLabel(NULL);
6985
6986             while(size--) {
6987               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6988               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6989
6990               if ( IC_TRUE(ifx) ) {
6991                 if(size) {
6992                   emitSKPZ;
6993                 
6994                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6995
6996                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6997                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6998                 } else {
6999                   emitSKPNZ;
7000
7001                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7002
7003
7004                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7005                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7006                 }
7007               } else {
7008                 emitSKPZ;
7009
7010                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7011
7012                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7013                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7014               }
7015               offset++;
7016             }
7017             if(s>1 && IC_TRUE(ifx)) {
7018               pic16_emitpLabel(tlbl->key);
7019               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7020             }
7021           }
7022         }
7023         /* mark the icode as generated */
7024         ifx->generated = 1;
7025         goto release ;
7026     }
7027
7028     /* if they are both bit variables */
7029     if (AOP_TYPE(left) == AOP_CRY &&
7030         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7031         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7032         if(AOP_TYPE(right) == AOP_LIT){
7033             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7034             if(lit == 0L){
7035                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036                 pic16_emitcode("cpl","c");
7037             } else if(lit == 1L) {
7038                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7039             } else {
7040                 pic16_emitcode("clr","c");
7041             }
7042             /* AOP_TYPE(right) == AOP_CRY */
7043         } else {
7044             symbol *lbl = newiTempLabel(NULL);
7045             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7047             pic16_emitcode("cpl","c");
7048             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7049         }
7050         /* c = 1 if egal */
7051         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7052             pic16_outBitC(result);
7053             goto release ;
7054         }
7055         if (ifx) {
7056             genIfxJump (ifx,"c");
7057             goto release ;
7058         }
7059         /* if the result is used in an arithmetic operation
7060         then put the result in place */
7061         pic16_outBitC(result);
7062     } else {
7063       
7064       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7065       gencjne(left,right,result,ifx);
7066 /*
7067       if(ifx) 
7068         gencjne(left,right,newiTempLabel(NULL));
7069       else {
7070         if(IC_TRUE(ifx)->key)
7071           gencjne(left,right,IC_TRUE(ifx)->key);
7072         else
7073           gencjne(left,right,IC_FALSE(ifx)->key);
7074         ifx->generated = 1;
7075         goto release ;
7076       }
7077       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7078         pic16_aopPut(AOP(result),"a",0);
7079         goto release ;
7080       }
7081
7082       if (ifx) {
7083         genIfxJump (ifx,"a");
7084         goto release ;
7085       }
7086 */
7087       /* if the result is used in an arithmetic operation
7088          then put the result in place */
7089 /*
7090       if (AOP_TYPE(result) != AOP_CRY) 
7091         pic16_outAcc(result);
7092 */
7093       /* leave the result in acc */
7094     }
7095
7096 release:
7097     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7098     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7099     pic16_freeAsmop(result,NULL,ic,TRUE);
7100 }
7101 #endif
7102
7103 /*-----------------------------------------------------------------*/
7104 /* ifxForOp - returns the icode containing the ifx for operand     */
7105 /*-----------------------------------------------------------------*/
7106 static iCode *ifxForOp ( operand *op, iCode *ic )
7107 {
7108   FENTRY2;
7109
7110     /* if true symbol then needs to be assigned */
7111     if (IS_TRUE_SYMOP(op))
7112         return NULL ;
7113
7114     /* if this has register type condition and
7115     the next instruction is ifx with the same operand
7116     and live to of the operand is upto the ifx only then */
7117     if (ic->next
7118         && ic->next->op == IFX
7119         && IC_COND(ic->next)->key == op->key
7120         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7121         ) {
7122                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7123           return ic->next;
7124     }
7125
7126     /*
7127     if (ic->next &&
7128         ic->next->op == IFX &&
7129         IC_COND(ic->next)->key == op->key) {
7130       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7131       return ic->next;
7132     }
7133     */
7134
7135     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7136     if (ic->next &&
7137         ic->next->op == IFX)
7138       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7139
7140     if (ic->next &&
7141         ic->next->op == IFX &&
7142         IC_COND(ic->next)->key == op->key) {
7143       DEBUGpic16_emitcode ("; "," key is okay");
7144       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7145                            OP_SYMBOL(op)->liveTo,
7146                            ic->next->seq);
7147     }
7148
7149 #if 0
7150     /* the code below is completely untested
7151      * it just allows ulong2fs.c compile -- VR */
7152          
7153     ic = ic->next;
7154     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7155                                         __FILE__, __FUNCTION__, __LINE__);
7156         
7157     /* if this has register type condition and
7158     the next instruction is ifx with the same operand
7159     and live to of the operand is upto the ifx only then */
7160     if (ic->next &&
7161         ic->next->op == IFX &&
7162         IC_COND(ic->next)->key == op->key &&
7163         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7164         return ic->next;
7165
7166     if (ic->next &&
7167         ic->next->op == IFX &&
7168         IC_COND(ic->next)->key == op->key) {
7169       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7170       return ic->next;
7171     }
7172
7173     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7174                                         __FILE__, __FUNCTION__, __LINE__);
7175
7176 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7177 #endif
7178
7179     return NULL;
7180 }
7181 /*-----------------------------------------------------------------*/
7182 /* genAndOp - for && operation                                     */
7183 /*-----------------------------------------------------------------*/
7184 static void genAndOp (iCode *ic)
7185 {
7186   operand *left,*right, *result;
7187 /*     symbol *tlbl; */
7188
7189     FENTRY;
7190
7191     /* note here that && operations that are in an
7192     if statement are taken away by backPatchLabels
7193     only those used in arthmetic operations remain */
7194     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7195     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7196     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7197
7198     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7199
7200     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7201     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7202     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7203
7204     /* if both are bit variables */
7205 /*     if (AOP_TYPE(left) == AOP_CRY && */
7206 /*         AOP_TYPE(right) == AOP_CRY ) { */
7207 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7208 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7209 /*         pic16_outBitC(result); */
7210 /*     } else { */
7211 /*         tlbl = newiTempLabel(NULL); */
7212 /*         pic16_toBoolean(left);     */
7213 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7214 /*         pic16_toBoolean(right); */
7215 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7216 /*         pic16_outBitAcc(result); */
7217 /*     } */
7218
7219     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7220     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7221     pic16_freeAsmop(result,NULL,ic,TRUE);
7222 }
7223
7224
7225 /*-----------------------------------------------------------------*/
7226 /* genOrOp - for || operation                                      */
7227 /*-----------------------------------------------------------------*/
7228 /*
7229   tsd pic port -
7230   modified this code, but it doesn't appear to ever get called
7231 */
7232
7233 static void genOrOp (iCode *ic)
7234 {
7235   operand *left,*right, *result;
7236   symbol *tlbl;
7237
7238     FENTRY;  
7239
7240   /* note here that || operations that are in an
7241     if statement are taken away by backPatchLabels
7242     only those used in arthmetic operations remain */
7243     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7244     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7245     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7246
7247     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7248
7249     /* if both are bit variables */
7250     if (AOP_TYPE(left) == AOP_CRY &&
7251         AOP_TYPE(right) == AOP_CRY ) {
7252       pic16_emitcode("clrc","");
7253       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7254                AOP(left)->aopu.aop_dir,
7255                AOP(left)->aopu.aop_dir);
7256       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7257                AOP(right)->aopu.aop_dir,
7258                AOP(right)->aopu.aop_dir);
7259       pic16_emitcode("setc","");
7260
7261     } else {
7262         tlbl = newiTempLabel(NULL);
7263         pic16_toBoolean(left);
7264         emitSKPZ;
7265         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7266         pic16_toBoolean(right);
7267         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7268
7269         pic16_outBitAcc(result);
7270     }
7271
7272     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7273     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7274     pic16_freeAsmop(result,NULL,ic,TRUE);            
7275 }
7276
7277 /*-----------------------------------------------------------------*/
7278 /* isLiteralBit - test if lit == 2^n                               */
7279 /*-----------------------------------------------------------------*/
7280 static int isLiteralBit(unsigned long lit)
7281 {
7282     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7283     0x100L,0x200L,0x400L,0x800L,
7284     0x1000L,0x2000L,0x4000L,0x8000L,
7285     0x10000L,0x20000L,0x40000L,0x80000L,
7286     0x100000L,0x200000L,0x400000L,0x800000L,
7287     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7288     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7289     int idx;
7290     
7291     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7292     for(idx = 0; idx < 32; idx++)
7293         if(lit == pw[idx])
7294             return idx+1;
7295     return 0;
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* continueIfTrue -                                                */
7300 /*-----------------------------------------------------------------*/
7301 static void continueIfTrue (iCode *ic)
7302 {
7303   FENTRY;
7304   if(IC_TRUE(ic))
7305     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7306   ic->generated = 1;
7307 }
7308
7309 /*-----------------------------------------------------------------*/
7310 /* jmpIfTrue -                                                     */
7311 /*-----------------------------------------------------------------*/
7312 static void jumpIfTrue (iCode *ic)
7313 {
7314   FENTRY;
7315   if(!IC_TRUE(ic))
7316     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7317   ic->generated = 1;
7318 }
7319
7320 /*-----------------------------------------------------------------*/
7321 /* jmpTrueOrFalse -                                                */
7322 /*-----------------------------------------------------------------*/
7323 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7324 {
7325   // ugly but optimized by peephole
7326   FENTRY;
7327   if(IC_TRUE(ic)){
7328     symbol *nlbl = newiTempLabel(NULL);
7329       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7330       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7331       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7332       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7333   } else {
7334     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7335     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7336   }
7337   ic->generated = 1;
7338 }
7339
7340 /*-----------------------------------------------------------------*/
7341 /* genAnd  - code for and                                          */
7342 /*-----------------------------------------------------------------*/
7343 static void genAnd (iCode *ic, iCode *ifx)
7344 {
7345   operand *left, *right, *result;
7346   int size, offset=0;  
7347   unsigned long lit = 0L;
7348   int bytelit = 0;
7349   resolvedIfx rIfx;
7350
7351     FENTRY;
7352     
7353   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7354   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7355   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7356
7357   resolveIfx(&rIfx,ifx);
7358
7359   /* if left is a literal & right is not then exchange them */
7360   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7361       AOP_NEEDSACC(left)) {
7362     operand *tmp = right ;
7363     right = left;
7364     left = tmp;
7365   }
7366
7367   /* if result = right then exchange them */
7368   if(pic16_sameRegs(AOP(result),AOP(right))){
7369     operand *tmp = right ;
7370     right = left;
7371     left = tmp;
7372   }
7373
7374   /* if right is bit then exchange them */
7375   if (AOP_TYPE(right) == AOP_CRY &&
7376       AOP_TYPE(left) != AOP_CRY){
7377     operand *tmp = right ;
7378     right = left;
7379     left = tmp;
7380   }
7381   if(AOP_TYPE(right) == AOP_LIT)
7382     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7383
7384   size = AOP_SIZE(result);
7385
7386   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7387
7388   // if(bit & yy)
7389   // result = bit & yy;
7390   if (AOP_TYPE(left) == AOP_CRY){
7391     // c = bit & literal;
7392     if(AOP_TYPE(right) == AOP_LIT){
7393       if(lit & 1) {
7394         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7395           // no change
7396           goto release;
7397         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7398       } else {
7399         // bit(result) = 0;
7400         if(size && (AOP_TYPE(result) == AOP_CRY)){
7401           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7402           goto release;
7403         }
7404         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7405           jumpIfTrue(ifx);
7406           goto release;
7407         }
7408         pic16_emitcode("clr","c");
7409       }
7410     } else {
7411       if (AOP_TYPE(right) == AOP_CRY){
7412         // c = bit & bit;
7413         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7414         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7415       } else {
7416         // c = bit & val;
7417         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7418         // c = lsb
7419         pic16_emitcode("rrc","a");
7420         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421       }
7422     }
7423     // bit = c
7424     // val = c
7425     if(size)
7426       pic16_outBitC(result);
7427     // if(bit & ...)
7428     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7429       genIfxJump(ifx, "c");           
7430     goto release ;
7431   }
7432
7433   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7434   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7435   if((AOP_TYPE(right) == AOP_LIT) &&
7436      (AOP_TYPE(result) == AOP_CRY) &&
7437      (AOP_TYPE(left) != AOP_CRY)){
7438     int posbit = isLiteralBit(lit);
7439     /* left &  2^n */
7440     if(posbit){
7441       posbit--;
7442       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7443       // bit = left & 2^n
7444       if(size)
7445         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7446       // if(left &  2^n)
7447       else{
7448         if(ifx){
7449 /*
7450           if(IC_TRUE(ifx)) {
7451             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7452             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7453           } else {
7454             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7455             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7456           }
7457 */
7458         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7459         size = AOP_SIZE(left);
7460
7461         {
7462           int bp = posbit, ofs=0;
7463           
7464             while(bp > 7) {
7465               bp -= 8;
7466               ofs++;
7467             }
7468         
7469           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7470                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7471
7472         }
7473 /*
7474           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7475                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7476 */
7477           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7478           
7479           ifx->generated = 1;
7480         }
7481         goto release;
7482       }
7483     } else {
7484       symbol *tlbl = newiTempLabel(NULL);
7485       int sizel = AOP_SIZE(left);
7486
7487       if(size)
7488         emitSETC;
7489
7490       while(sizel--) {
7491         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7492
7493           /* patch provided by Aaron Colwell */
7494           if((posbit = isLiteralBit(bytelit)) != 0) {
7495               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7496                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7497                                                 (posbit-1),0, PO_GPR_REGISTER));
7498
7499               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7500 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7501           } else {
7502               if (bytelit == 0xff) {
7503                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7504                    * a peephole could optimize it out -- VR */
7505                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7506               } else {
7507                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7508                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7509               }
7510
7511               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7512                             pic16_popGetLabel(tlbl->key));
7513           }
7514         
7515 #if 0
7516           /* old code, left here for reference -- VR 09/2004 */
7517           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7518           // byte ==  2^n ?
7519           if((posbit = isLiteralBit(bytelit)) != 0)
7520             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7521           else{
7522             if(bytelit != 0x0FFL)
7523               pic16_emitcode("anl","a,%s",
7524                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7525             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7526           }
7527 #endif
7528         }
7529         offset++;
7530       }
7531       // bit = left & literal
7532       if(size) {
7533         emitCLRC;
7534         pic16_emitpLabel(tlbl->key);
7535       }
7536       // if(left & literal)
7537       else {
7538         if(ifx) {
7539           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7540           ifx->generated = 1;
7541         }
7542         pic16_emitpLabel(tlbl->key);
7543         goto release;
7544       }
7545     }
7546
7547     pic16_outBitC(result);
7548     goto release ;
7549   }
7550
7551   /* if left is same as result */
7552   if(pic16_sameRegs(AOP(result),AOP(left))){
7553     int know_W = -1;
7554     for(;size--; offset++,lit>>=8) {
7555       if(AOP_TYPE(right) == AOP_LIT){
7556         switch(lit & 0xff) {
7557         case 0x00:
7558           /*  and'ing with 0 has clears the result */
7559 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7560           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7561           break;
7562         case 0xff:
7563           /* and'ing with 0xff is a nop when the result and left are the same */
7564           break;
7565
7566         default:
7567           {
7568             int p = pic16_my_powof2( (~lit) & 0xff );
7569             if(p>=0) {
7570               /* only one bit is set in the literal, so use a bcf instruction */
7571 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7572               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7573
7574             } else {
7575               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7576               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7577               if(know_W != (lit&0xff))
7578                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7579               know_W = lit &0xff;
7580               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7581             }
7582           }    
7583         }
7584       } else {
7585         if (AOP_TYPE(left) == AOP_ACC) {
7586           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7587         } else {                    
7588           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7589           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7590
7591         }
7592       }
7593     }
7594
7595   } else {
7596     // left & result in different registers
7597     if(AOP_TYPE(result) == AOP_CRY){
7598       // result = bit
7599       // if(size), result in bit
7600       // if(!size && ifx), conditional oper: if(left & right)
7601       symbol *tlbl = newiTempLabel(NULL);
7602       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7603       if(size)
7604         pic16_emitcode("setb","c");
7605       while(sizer--){
7606         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7607         pic16_emitcode("anl","a,%s",
7608                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7609         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7610         offset++;
7611       }
7612       if(size){
7613         CLRC;
7614         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7615         pic16_outBitC(result);
7616       } else if(ifx)
7617         jmpTrueOrFalse(ifx, tlbl);
7618     } else {
7619       for(;(size--);offset++) {
7620         // normal case
7621         // result = left & right
7622         if(AOP_TYPE(right) == AOP_LIT){
7623           int t = (lit >> (offset*8)) & 0x0FFL;
7624           switch(t) { 
7625           case 0x00:
7626             pic16_emitcode("clrf","%s",
7627                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7628             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7629             break;
7630           case 0xff:
7631             pic16_emitcode("movf","%s,w",
7632                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7633             pic16_emitcode("movwf","%s",
7634                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7635             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7636             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7637             break;
7638           default:
7639             pic16_emitcode("movlw","0x%x",t);
7640             pic16_emitcode("andwf","%s,w",
7641                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7642             pic16_emitcode("movwf","%s",
7643                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7644               
7645             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7646             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7647             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7648           }
7649           continue;
7650         }
7651
7652         if (AOP_TYPE(left) == AOP_ACC) {
7653           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7654           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7655         } else {
7656           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657           pic16_emitcode("andwf","%s,w",
7658                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7659           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7660           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7661         }
7662         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7663         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7664       }
7665     }
7666   }
7667
7668   release :
7669     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7670   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7671   pic16_freeAsmop(result,NULL,ic,TRUE);     
7672 }
7673
7674 /*-----------------------------------------------------------------*/
7675 /* genOr  - code for or                                            */
7676 /*-----------------------------------------------------------------*/
7677 static void genOr (iCode *ic, iCode *ifx)
7678 {
7679     operand *left, *right, *result;
7680     int size, offset=0;
7681     unsigned long lit = 0L;
7682
7683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7684
7685     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7686     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7687     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7688
7689     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7690
7691     /* if left is a literal & right is not then exchange them */
7692     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7693         AOP_NEEDSACC(left)) {
7694         operand *tmp = right ;
7695         right = left;
7696         left = tmp;
7697     }
7698
7699     /* if result = right then exchange them */
7700     if(pic16_sameRegs(AOP(result),AOP(right))){
7701         operand *tmp = right ;
7702         right = left;
7703         left = tmp;
7704     }
7705
7706     /* if right is bit then exchange them */
7707     if (AOP_TYPE(right) == AOP_CRY &&
7708         AOP_TYPE(left) != AOP_CRY){
7709         operand *tmp = right ;
7710         right = left;
7711         left = tmp;
7712     }
7713
7714     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7715
7716     if(AOP_TYPE(right) == AOP_LIT)
7717         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7718
7719     size = AOP_SIZE(result);
7720
7721     // if(bit | yy)
7722     // xx = bit | yy;
7723     if (AOP_TYPE(left) == AOP_CRY){
7724         if(AOP_TYPE(right) == AOP_LIT){
7725             // c = bit & literal;
7726             if(lit){
7727                 // lit != 0 => result = 1
7728                 if(AOP_TYPE(result) == AOP_CRY){
7729                   if(size)
7730                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7731                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7732                   //     AOP(result)->aopu.aop_dir,
7733                   //     AOP(result)->aopu.aop_dir);
7734                     else if(ifx)
7735                         continueIfTrue(ifx);
7736                     goto release;
7737                 }
7738             } else {
7739                 // lit == 0 => result = left
7740                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7741                     goto release;
7742                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7743             }
7744         } else {
7745             if (AOP_TYPE(right) == AOP_CRY){
7746               if(pic16_sameRegs(AOP(result),AOP(left))){
7747                 // c = bit | bit;
7748                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7749                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7750                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7751
7752                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7753                          AOP(result)->aopu.aop_dir,
7754                          AOP(result)->aopu.aop_dir);
7755                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7756                          AOP(right)->aopu.aop_dir,
7757                          AOP(right)->aopu.aop_dir);
7758                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7759                          AOP(result)->aopu.aop_dir,
7760                          AOP(result)->aopu.aop_dir);
7761               } else {
7762                 if( AOP_TYPE(result) == AOP_ACC) {
7763                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7764                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7765                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7766                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7767
7768                 } else {
7769
7770                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7771                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7772                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7773                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7774
7775                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7776                                  AOP(result)->aopu.aop_dir,
7777                                  AOP(result)->aopu.aop_dir);
7778                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7779                                  AOP(right)->aopu.aop_dir,
7780                                  AOP(right)->aopu.aop_dir);
7781                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7782                                  AOP(left)->aopu.aop_dir,
7783                                  AOP(left)->aopu.aop_dir);
7784                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7785                                  AOP(result)->aopu.aop_dir,
7786                                  AOP(result)->aopu.aop_dir);
7787                 }
7788               }
7789             } else {
7790                 // c = bit | val;
7791                 symbol *tlbl = newiTempLabel(NULL);
7792                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7793
7794
7795                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7796                 if( AOP_TYPE(right) == AOP_ACC) {
7797                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7798                   emitSKPNZ;
7799                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7800                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7801                 }
7802
7803
7804
7805                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7806                     pic16_emitcode(";XXX setb","c");
7807                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7808                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7809                 pic16_toBoolean(right);
7810                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7811                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7812                     jmpTrueOrFalse(ifx, tlbl);
7813                     goto release;
7814                 } else {
7815                     CLRC;
7816                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7817                 }
7818             }
7819         }
7820         // bit = c
7821         // val = c
7822         if(size)
7823             pic16_outBitC(result);
7824         // if(bit | ...)
7825         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7826             genIfxJump(ifx, "c");           
7827         goto release ;
7828     }
7829
7830     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7831     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7832     if((AOP_TYPE(right) == AOP_LIT) &&
7833        (AOP_TYPE(result) == AOP_CRY) &&
7834        (AOP_TYPE(left) != AOP_CRY)){
7835         if(lit){
7836           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7837             // result = 1
7838             if(size)
7839                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7840             else 
7841                 continueIfTrue(ifx);
7842             goto release;
7843         } else {
7844           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845             // lit = 0, result = boolean(left)
7846             if(size)
7847                 pic16_emitcode(";XXX setb","c");
7848             pic16_toBoolean(right);
7849             if(size){
7850                 symbol *tlbl = newiTempLabel(NULL);
7851                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7852                 CLRC;
7853                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7854             } else {
7855                 genIfxJump (ifx,"a");
7856                 goto release;
7857             }
7858         }
7859         pic16_outBitC(result);
7860         goto release ;
7861     }
7862
7863     /* if left is same as result */
7864     if(pic16_sameRegs(AOP(result),AOP(left))){
7865       int know_W = -1;
7866       for(;size--; offset++,lit>>=8) {
7867         if(AOP_TYPE(right) == AOP_LIT){
7868           if((lit & 0xff) == 0)
7869             /*  or'ing with 0 has no effect */
7870             continue;
7871           else {
7872             int p = pic16_my_powof2(lit & 0xff);
7873             if(p>=0) {
7874               /* only one bit is set in the literal, so use a bsf instruction */
7875               pic16_emitpcode(POC_BSF,
7876                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7877             } else {
7878               if(know_W != (lit & 0xff))
7879                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7880               know_W = lit & 0xff;
7881               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7882             }
7883                     
7884           }
7885         } else {
7886           if (AOP_TYPE(left) == AOP_ACC) {
7887             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7888             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7889           } else {                  
7890             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7891             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7892
7893             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7895
7896           }
7897         }
7898       }
7899     } else {
7900         // left & result in different registers
7901         if(AOP_TYPE(result) == AOP_CRY){
7902             // result = bit
7903             // if(size), result in bit
7904             // if(!size && ifx), conditional oper: if(left | right)
7905             symbol *tlbl = newiTempLabel(NULL);
7906             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7907             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7908
7909
7910             if(size)
7911                 pic16_emitcode(";XXX setb","c");
7912             while(sizer--){
7913                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914                 pic16_emitcode(";XXX orl","a,%s",
7915                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7916                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7917                 offset++;
7918             }
7919             if(size){
7920                 CLRC;
7921                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7922                 pic16_outBitC(result);
7923             } else if(ifx)
7924                 jmpTrueOrFalse(ifx, tlbl);
7925         } else for(;(size--);offset++){
7926           // normal case
7927           // result = left & right
7928           if(AOP_TYPE(right) == AOP_LIT){
7929             int t = (lit >> (offset*8)) & 0x0FFL;
7930             switch(t) { 
7931             case 0x00:
7932               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7933               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7934
7935               pic16_emitcode("movf","%s,w",
7936                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7937               pic16_emitcode("movwf","%s",
7938                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7939               break;
7940             default:
7941               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7942               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7943               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7944
7945               pic16_emitcode("movlw","0x%x",t);
7946               pic16_emitcode("iorwf","%s,w",
7947                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7948               pic16_emitcode("movwf","%s",
7949                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7950               
7951             }
7952             continue;
7953           }
7954
7955           // faster than result <- left, anl result,right
7956           // and better if result is SFR
7957           if (AOP_TYPE(left) == AOP_ACC) {
7958             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7959             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7960           } else {
7961             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7962             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7963
7964             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965             pic16_emitcode("iorwf","%s,w",
7966                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7967           }
7968           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7969           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7970         }
7971     }
7972
7973 release :
7974     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7975     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7976     pic16_freeAsmop(result,NULL,ic,TRUE);     
7977 }
7978
7979 /*-----------------------------------------------------------------*/
7980 /* genXor - code for xclusive or                                   */
7981 /*-----------------------------------------------------------------*/
7982 static void genXor (iCode *ic, iCode *ifx)
7983 {
7984   operand *left, *right, *result;
7985   int size, offset=0;
7986   unsigned long lit = 0L;
7987
7988   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7989
7990   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7991   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7992   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7993
7994   /* if left is a literal & right is not ||
7995      if left needs acc & right does not */
7996   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7997       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7998     operand *tmp = right ;
7999     right = left;
8000     left = tmp;
8001   }
8002
8003   /* if result = right then exchange them */
8004   if(pic16_sameRegs(AOP(result),AOP(right))){
8005     operand *tmp = right ;
8006     right = left;
8007     left = tmp;
8008   }
8009
8010   /* if right is bit then exchange them */
8011   if (AOP_TYPE(right) == AOP_CRY &&
8012       AOP_TYPE(left) != AOP_CRY){
8013     operand *tmp = right ;
8014     right = left;
8015     left = tmp;
8016   }
8017   if(AOP_TYPE(right) == AOP_LIT)
8018     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8019
8020   size = AOP_SIZE(result);
8021
8022   // if(bit ^ yy)
8023   // xx = bit ^ yy;
8024   if (AOP_TYPE(left) == AOP_CRY){
8025     if(AOP_TYPE(right) == AOP_LIT){
8026       // c = bit & literal;
8027       if(lit>>1){
8028         // lit>>1  != 0 => result = 1
8029         if(AOP_TYPE(result) == AOP_CRY){
8030           if(size)
8031             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8032             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8033           else if(ifx)
8034             continueIfTrue(ifx);
8035           goto release;
8036         }
8037         pic16_emitcode("setb","c");
8038       } else{
8039         // lit == (0 or 1)
8040         if(lit == 0){
8041           // lit == 0, result = left
8042           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8043             goto release;
8044           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8045         } else{
8046           // lit == 1, result = not(left)
8047           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8048             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8049             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8050             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8051             goto release;
8052           } else {
8053             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8054             pic16_emitcode("cpl","c");
8055           }
8056         }
8057       }
8058
8059     } else {
8060       // right != literal
8061       symbol *tlbl = newiTempLabel(NULL);
8062       if (AOP_TYPE(right) == AOP_CRY){
8063         // c = bit ^ bit;
8064         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8065       }
8066       else{
8067         int sizer = AOP_SIZE(right);
8068         // c = bit ^ val
8069         // if val>>1 != 0, result = 1
8070         pic16_emitcode("setb","c");
8071         while(sizer){
8072           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8073           if(sizer == 1)
8074             // test the msb of the lsb
8075             pic16_emitcode("anl","a,#0xfe");
8076           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8077           sizer--;
8078         }
8079         // val = (0,1)
8080         pic16_emitcode("rrc","a");
8081       }
8082       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8083       pic16_emitcode("cpl","c");
8084       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8085     }
8086     // bit = c
8087     // val = c
8088     if(size)
8089       pic16_outBitC(result);
8090     // if(bit | ...)
8091     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8092       genIfxJump(ifx, "c");           
8093     goto release ;
8094   }
8095
8096   if(pic16_sameRegs(AOP(result),AOP(left))){
8097     /* if left is same as result */
8098     for(;size--; offset++) {
8099       if(AOP_TYPE(right) == AOP_LIT){
8100         int t  = (lit >> (offset*8)) & 0x0FFL;
8101         if(t == 0x00L)
8102           continue;
8103         else
8104           if (IS_AOP_PREG(left)) {
8105             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8106             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8107             pic16_aopPut(AOP(result),"a",offset);
8108           } else {
8109             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8110             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8111             pic16_emitcode("xrl","%s,%s",
8112                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8113                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114           }
8115       } else {
8116         if (AOP_TYPE(left) == AOP_ACC)
8117           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118         else {
8119           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8120           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8121 /*
8122           if (IS_AOP_PREG(left)) {
8123             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8124             pic16_aopPut(AOP(result),"a",offset);
8125           } else
8126             pic16_emitcode("xrl","%s,a",
8127                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8128 */
8129         }
8130       }
8131     }
8132   } else {
8133     // left & result in different registers
8134     if(AOP_TYPE(result) == AOP_CRY){
8135       // result = bit
8136       // if(size), result in bit
8137       // if(!size && ifx), conditional oper: if(left ^ right)
8138       symbol *tlbl = newiTempLabel(NULL);
8139       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8140       if(size)
8141         pic16_emitcode("setb","c");
8142       while(sizer--){
8143         if((AOP_TYPE(right) == AOP_LIT) &&
8144            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8145           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8146         } else {
8147           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148           pic16_emitcode("xrl","a,%s",
8149                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8150         }
8151         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8152         offset++;
8153       }
8154       if(size){
8155         CLRC;
8156         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8157         pic16_outBitC(result);
8158       } else if(ifx)
8159         jmpTrueOrFalse(ifx, tlbl);
8160     } else for(;(size--);offset++){
8161       // normal case
8162       // result = left & right
8163       if(AOP_TYPE(right) == AOP_LIT){
8164         int t = (lit >> (offset*8)) & 0x0FFL;
8165         switch(t) { 
8166         case 0x00:
8167           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8168           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8169           pic16_emitcode("movf","%s,w",
8170                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8171           pic16_emitcode("movwf","%s",
8172                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8173           break;
8174         case 0xff:
8175           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8176           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177           pic16_emitcode("comf","%s,w",
8178                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179           pic16_emitcode("movwf","%s",
8180                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181           break;
8182         default:
8183           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8184           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8185           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8186           pic16_emitcode("movlw","0x%x",t);
8187           pic16_emitcode("xorwf","%s,w",
8188                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189           pic16_emitcode("movwf","%s",
8190                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191
8192         }
8193         continue;
8194       }
8195
8196       // faster than result <- left, anl result,right
8197       // and better if result is SFR
8198       if (AOP_TYPE(left) == AOP_ACC) {
8199         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8200         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8201       } else {
8202         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8203         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8204         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8205         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8206       }
8207       if ( AOP_TYPE(result) != AOP_ACC){
8208         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8209         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8210       }
8211     }
8212   }
8213
8214   release :
8215     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8216   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8217   pic16_freeAsmop(result,NULL,ic,TRUE);     
8218 }
8219
8220 /*-----------------------------------------------------------------*/
8221 /* genInline - write the inline code out                           */
8222 /*-----------------------------------------------------------------*/
8223 static void genInline (iCode *ic)
8224 {
8225   char *buffer, *bp, *bp1;
8226   char *cbuf;
8227     
8228         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8229
8230         _G.inLine += (!options.asmpeep);
8231
8232         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8233         strcpy(buffer,IC_INLINE(ic));
8234         
8235         while((bp1=strstr(bp, "\\n"))) {
8236           *bp1++ = '\n';
8237           *bp1++ = ' ';
8238           bp = bp1;
8239         }
8240         bp = bp1 = buffer;
8241
8242         cbuf = Safe_strdup( buffer );
8243
8244         if(asmInlineMap)
8245         {
8246           symbol *sym;
8247           char *s;
8248           int cblen;
8249
8250             cbuf = Safe_strdup(buffer);
8251             cblen = strlen(buffer)+1;
8252             memset(cbuf, 0, cblen);
8253
8254             bp = buffer;
8255             bp1 = cbuf;
8256             while(*bp) {
8257               if(*bp != '%')*bp1++ = *bp++;
8258               else {
8259                 int i;
8260
8261                   bp++;
8262                   i = *bp - '0';
8263                   if(i>elementsInSet(asmInlineMap))break;
8264                   
8265                   bp++;
8266                   s = indexSet(asmInlineMap, i);
8267                   DEBUGpc("searching symbol s = `%s'", s);
8268                   sym = findSym(SymbolTab, NULL, s);
8269
8270                   if(sym->reqv) {
8271                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8272                   } else {
8273                     strcat(bp1, sym->rname);
8274                   }
8275                   
8276                   while(*bp1)bp1++;
8277               }
8278               
8279               if(strlen(bp1) > cblen - 16) {
8280                 int i = strlen(cbuf);
8281                 cblen += 50;
8282                 cbuf = realloc(cbuf, cblen);
8283                 memset(cbuf+i, 0, 50);
8284                 bp1 = cbuf + i;
8285               }
8286             }
8287             
8288             free(buffer);
8289             buffer = Safe_strdup( cbuf );
8290             free(cbuf);
8291             
8292             bp = bp1 = buffer;
8293         }
8294
8295         /* emit each line as a code */
8296         while (*bp) {
8297                 if (*bp == '\n') {
8298                         *bp++ = '\0';
8299
8300                         if(*bp1)
8301                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8302                         bp1 = bp;
8303                 } else {
8304                         if (*bp == ':') {
8305                                 bp++;
8306                                 *bp = '\0';
8307                                 bp++;
8308
8309                                 /* print label, use this special format with NULL directive
8310                                  * to denote that the argument should not be indented with tab */
8311                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8312                                 bp1 = bp;
8313                         } else
8314                                 bp++;
8315                 }
8316         }
8317
8318         if ((bp1 != bp) && *bp1)
8319                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8320
8321
8322     Safe_free(buffer);
8323
8324     _G.inLine -= (!options.asmpeep);
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* genRRC - rotate right with carry                                */
8329 /*-----------------------------------------------------------------*/
8330 static void genRRC (iCode *ic)
8331 {
8332   operand *left , *result ;
8333   int size, offset = 0, same;
8334
8335   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8336
8337   /* rotate right with carry */
8338   left = IC_LEFT(ic);
8339   result=IC_RESULT(ic);
8340   pic16_aopOp (left,ic,FALSE);
8341   pic16_aopOp (result,ic,TRUE);
8342
8343   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8344
8345   same = pic16_sameRegs(AOP(result),AOP(left));
8346
8347   size = AOP_SIZE(result);    
8348
8349   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8350
8351   /* get the lsb and put it into the carry */
8352   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8353
8354   offset = 0 ;
8355
8356   while(size--) {
8357
8358     if(same) {
8359       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8360     } else {
8361       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8362       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8363     }
8364
8365     offset++;
8366   }
8367
8368   pic16_freeAsmop(left,NULL,ic,TRUE);
8369   pic16_freeAsmop(result,NULL,ic,TRUE);
8370 }
8371
8372 /*-----------------------------------------------------------------*/
8373 /* genRLC - generate code for rotate left with carry               */
8374 /*-----------------------------------------------------------------*/
8375 static void genRLC (iCode *ic)
8376 {    
8377   operand *left , *result ;
8378   int size, offset = 0;
8379   int same;
8380
8381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8382   /* rotate right with carry */
8383   left = IC_LEFT(ic);
8384   result=IC_RESULT(ic);
8385   pic16_aopOp (left,ic,FALSE);
8386   pic16_aopOp (result,ic,TRUE);
8387
8388   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8389
8390   same = pic16_sameRegs(AOP(result),AOP(left));
8391
8392   /* move it to the result */
8393   size = AOP_SIZE(result);    
8394
8395   /* get the msb and put it into the carry */
8396   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8397
8398   offset = 0 ;
8399
8400   while(size--) {
8401
8402     if(same) {
8403       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8404     } else {
8405       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8406       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8407     }
8408
8409     offset++;
8410   }
8411
8412
8413   pic16_freeAsmop(left,NULL,ic,TRUE);
8414   pic16_freeAsmop(result,NULL,ic,TRUE);
8415 }
8416
8417
8418 /* gpasm can get the highest order bit with HIGH/UPPER
8419  * so the following probably is not needed -- VR */
8420  
8421 /*-----------------------------------------------------------------*/
8422 /* genGetHbit - generates code get highest order bit               */
8423 /*-----------------------------------------------------------------*/
8424 static void genGetHbit (iCode *ic)
8425 {
8426     operand *left, *result;
8427     left = IC_LEFT(ic);
8428     result=IC_RESULT(ic);
8429     pic16_aopOp (left,ic,FALSE);
8430     pic16_aopOp (result,ic,FALSE);
8431
8432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8433     /* get the highest order byte into a */
8434     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8435     if(AOP_TYPE(result) == AOP_CRY){
8436         pic16_emitcode("rlc","a");
8437         pic16_outBitC(result);
8438     }
8439     else{
8440         pic16_emitcode("rl","a");
8441         pic16_emitcode("anl","a,#0x01");
8442         pic16_outAcc(result);
8443     }
8444
8445
8446     pic16_freeAsmop(left,NULL,ic,TRUE);
8447     pic16_freeAsmop(result,NULL,ic,TRUE);
8448 }
8449
8450 #if 0
8451 /*-----------------------------------------------------------------*/
8452 /* AccRol - rotate left accumulator by known count                 */
8453 /*-----------------------------------------------------------------*/
8454 static void AccRol (int shCount)
8455 {
8456     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8457     shCount &= 0x0007;              // shCount : 0..7
8458     switch(shCount){
8459         case 0 :
8460             break;
8461         case 1 :
8462             pic16_emitcode("rl","a");
8463             break;
8464         case 2 :
8465             pic16_emitcode("rl","a");
8466             pic16_emitcode("rl","a");
8467             break;
8468         case 3 :
8469             pic16_emitcode("swap","a");
8470             pic16_emitcode("rr","a");
8471             break;
8472         case 4 :
8473             pic16_emitcode("swap","a");
8474             break;
8475         case 5 :
8476             pic16_emitcode("swap","a");
8477             pic16_emitcode("rl","a");
8478             break;
8479         case 6 :
8480             pic16_emitcode("rr","a");
8481             pic16_emitcode("rr","a");
8482             break;
8483         case 7 :
8484             pic16_emitcode("rr","a");
8485             break;
8486     }
8487 }
8488 #endif
8489
8490 /*-----------------------------------------------------------------*/
8491 /* AccLsh - left shift accumulator by known count                  */
8492 /*-----------------------------------------------------------------*/
8493 static void AccLsh (int shCount)
8494 {
8495         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8496         switch(shCount){
8497                 case 0 :
8498                         return;
8499                         break;
8500                 case 1 :
8501                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502                         break;
8503                 case 2 :
8504                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8506                         break;
8507                 case 3 :
8508                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8509                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510                         break;
8511                 case 4 :
8512                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         break;
8514                 case 5 :
8515                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         break;
8518                 case 6 :
8519                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 7 :
8523                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         break;
8525         }
8526
8527         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8528 }
8529
8530 /*-----------------------------------------------------------------*/
8531 /* AccRsh - right shift accumulator by known count                 */
8532 /*-----------------------------------------------------------------*/
8533 static void AccRsh (int shCount, int andmask)
8534 {
8535         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8536         switch(shCount){
8537                 case 0 :
8538                         return; break;
8539                 case 1 :
8540                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8541                         break;
8542                 case 2 :
8543                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8545                         break;
8546                 case 3 :
8547                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8548                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         break;
8550                 case 4 :
8551                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         break;
8553                 case 5 :
8554                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8555                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         break;
8557                 case 6 :
8558                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         break;
8561                 case 7 :
8562                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         break;
8564         }
8565         
8566         if(andmask)
8567                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8568         else
8569                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8570 }
8571
8572 #if 0
8573 /*-----------------------------------------------------------------*/
8574 /* AccSRsh - signed right shift accumulator by known count                 */
8575 /*-----------------------------------------------------------------*/
8576 static void AccSRsh (int shCount)
8577 {
8578     symbol *tlbl ;
8579     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8580     if(shCount != 0){
8581         if(shCount == 1){
8582             pic16_emitcode("mov","c,acc.7");
8583             pic16_emitcode("rrc","a");
8584         } else if(shCount == 2){
8585             pic16_emitcode("mov","c,acc.7");
8586             pic16_emitcode("rrc","a");
8587             pic16_emitcode("mov","c,acc.7");
8588             pic16_emitcode("rrc","a");
8589         } else {
8590             tlbl = newiTempLabel(NULL);
8591             /* rotate right accumulator */
8592             AccRol(8 - shCount);
8593             /* and kill the higher order bits */
8594             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8595             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8596             pic16_emitcode("orl","a,#0x%02x",
8597                      (unsigned char)~SRMask[shCount]);
8598             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8599         }
8600     }
8601 }
8602 #endif
8603
8604 /*-----------------------------------------------------------------*/
8605 /* shiftR1Left2Result - shift right one byte from left to result   */
8606 /*-----------------------------------------------------------------*/
8607 static void shiftR1Left2ResultSigned (operand *left, int offl,
8608                                 operand *result, int offr,
8609                                 int shCount)
8610 {
8611   int same;
8612
8613   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8614
8615   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8616
8617   switch(shCount) {
8618   case 1:
8619     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8620     if(same) 
8621       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8622     else {
8623       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8624       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8625     }
8626
8627     break;
8628   case 2:
8629
8630     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8631     if(same) 
8632       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8633     else {
8634       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8635       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8636     }
8637     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8638     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8639
8640     break;
8641
8642   case 3:
8643     if(same)
8644       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8645     else {
8646       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8647       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8648     }
8649
8650     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8651     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8652     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8653
8654     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8655     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8656
8657     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658     break;
8659
8660   case 4:
8661     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8662     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8663     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8664     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8665     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8666     break;
8667   case 5:
8668     if(same) {
8669       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8670     } else {
8671       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8672       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8673     }
8674     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8675     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8676     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8677     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8678     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8679     break;
8680
8681   case 6:
8682     if(same) {
8683       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8684       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8686       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8687       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8688       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689     } else {
8690       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8691       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8692       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8693       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8694       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8695     }
8696     break;
8697
8698   case 7:
8699     if(same) {
8700       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8701       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8703       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704     } else {
8705       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8706       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8707       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8708     }
8709
8710   default:
8711     break;
8712   }
8713 }
8714
8715 /*-----------------------------------------------------------------*/
8716 /* shiftR1Left2Result - shift right one byte from left to result   */
8717 /*-----------------------------------------------------------------*/
8718 static void shiftR1Left2Result (operand *left, int offl,
8719                                 operand *result, int offr,
8720                                 int shCount, int sign)
8721 {
8722   int same;
8723
8724   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8725
8726   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8727
8728   /* Copy the msb into the carry if signed. */
8729   if(sign) {
8730     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8731     return;
8732   }
8733
8734
8735
8736   switch(shCount) {
8737   case 1:
8738     emitCLRC;
8739     if(same) 
8740       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8741     else {
8742       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8743       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8744     }
8745     break;
8746   case 2:
8747     emitCLRC;
8748     if(same) {
8749       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8750     } else {
8751       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8752       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8753     }
8754     emitCLRC;
8755     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8756
8757     break;
8758   case 3:
8759     if(same)
8760       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8761     else {
8762       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8763       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8764     }
8765
8766     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8767     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8768     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8769     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770     break;
8771       
8772   case 4:
8773     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8774     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8775     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776     break;
8777
8778   case 5:
8779     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8781     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782     //emitCLRC;
8783     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8784
8785     break;
8786   case 6:
8787
8788     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8790     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8792     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8793     break;
8794
8795   case 7:
8796
8797     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8798     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8799     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8800
8801     break;
8802
8803   default:
8804     break;
8805   }
8806 }
8807
8808 /*-----------------------------------------------------------------*/
8809 /* shiftL1Left2Result - shift left one byte from left to result    */
8810 /*-----------------------------------------------------------------*/
8811 static void shiftL1Left2Result (operand *left, int offl,
8812                                 operand *result, int offr, int shCount)
8813 {
8814   int same;
8815
8816   //    char *l;
8817   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8818
8819   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8820   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8821     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8822     //    MOVA(l);
8823     /* shift left accumulator */
8824     //AccLsh(shCount); // don't comment out just yet...
8825   //    pic16_aopPut(AOP(result),"a",offr);
8826
8827   switch(shCount) {
8828   case 1:
8829     /* Shift left 1 bit position */
8830     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8831     if(same) {
8832       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8833     } else {
8834       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8835       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8836     }
8837     break;
8838   case 2:
8839     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8840     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8841     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8842     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8843     break;
8844   case 3:
8845     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8846     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8847     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8848     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8849     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8850     break;
8851   case 4:
8852     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8853     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8854     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8855     break;
8856   case 5:
8857     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8858     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8859     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8861     break;
8862   case 6:
8863     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8864     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8865     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8866     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8867     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8868     break;
8869   case 7:
8870     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8871     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8872     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8873     break;
8874
8875   default:
8876     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8877   }
8878
8879 }
8880
8881 /*-----------------------------------------------------------------*/
8882 /* movLeft2Result - move byte from left to result                  */
8883 /*-----------------------------------------------------------------*/
8884 static void movLeft2Result (operand *left, int offl,
8885                             operand *result, int offr)
8886 {
8887   char *l;
8888   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8889   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8890     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8891
8892     if (*l == '@' && (IS_AOP_PREG(result))) {
8893       pic16_emitcode("mov","a,%s",l);
8894       pic16_aopPut(AOP(result),"a",offr);
8895     } else {
8896       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8897       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8898     }
8899   }
8900 }
8901
8902 /*-----------------------------------------------------------------*/
8903 /* shiftL2Left2Result - shift left two bytes from left to result   */
8904 /*-----------------------------------------------------------------*/
8905 static void shiftL2Left2Result (operand *left, int offl,
8906                                 operand *result, int offr, int shCount)
8907 {
8908   int same = pic16_sameRegs(AOP(result), AOP(left));
8909   int i;
8910
8911   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8912
8913   if (same && (offl != offr)) { // shift bytes
8914     if (offr > offl) {
8915        for(i=1;i>-1;i--) {
8916          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8917          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8918        }
8919     } else { // just treat as different later on
8920                 same = 0;
8921     }
8922   }
8923
8924   if(same) {
8925     switch(shCount) {
8926     case 0:
8927       break;
8928     case 1:
8929     case 2:
8930     case 3:
8931
8932       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8933       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8934       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8935
8936       while(--shCount) {
8937                 emitCLRC;
8938                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8939                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8940       }
8941
8942       break;
8943     case 4:
8944     case 5:
8945       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8946       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8947       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8948       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8950       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8952       if(shCount >=5) {
8953                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8954                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8955       }
8956       break;
8957     case 6:
8958       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8959       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
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_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8963       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8964       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8965       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8968       break;
8969     case 7:
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8975     }
8976
8977   } else {
8978     switch(shCount) {
8979     case 0:
8980       break;
8981     case 1:
8982     case 2:
8983     case 3:
8984       /* note, use a mov/add for the shift since the mov has a
8985          chance of getting optimized out */
8986       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8987       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8989       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8990       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8991
8992       while(--shCount) {
8993                 emitCLRC;
8994                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8995                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8996       }
8997       break;
8998
8999     case 4:
9000     case 5:
9001       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9002       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9003       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9004       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9005       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9006       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9007       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9008       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9009
9010
9011       if(shCount == 5) {
9012                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9013                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9014       }
9015       break;
9016     case 6:
9017       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9018       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9019       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9020       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9021
9022       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9023       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9026       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9028       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9030       break;
9031     case 7:
9032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9033       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9035       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9037     }
9038   }
9039
9040 }
9041 /*-----------------------------------------------------------------*/
9042 /* shiftR2Left2Result - shift right two bytes from left to result  */
9043 /*-----------------------------------------------------------------*/
9044 static void shiftR2Left2Result (operand *left, int offl,
9045                                 operand *result, int offr,
9046                                 int shCount, int sign)
9047 {
9048   int same = pic16_sameRegs(AOP(result), AOP(left));
9049   int i;
9050   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9051
9052   if (same && (offl != offr)) { // shift right bytes
9053     if (offr < offl) {
9054        for(i=0;i<2;i++) {
9055          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9056          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9057        }
9058     } else { // just treat as different later on
9059                 same = 0;
9060     }
9061   }
9062
9063   switch(shCount) {
9064   case 0:
9065     break;
9066   case 1:
9067   case 2:
9068   case 3:
9069     if(sign)
9070       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9071     else
9072       emitCLRC;
9073
9074     if(same) {
9075       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9076       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9077     } else {
9078       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9079       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9080       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9081       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9082     }
9083
9084     while(--shCount) {
9085       if(sign)
9086                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9087       else
9088                 emitCLRC;
9089       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9090       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9091     }
9092     break;
9093   case 4:
9094   case 5:
9095     if(same) {
9096
9097       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9098       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9099       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9100
9101       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9103       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9104       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9105     } else {
9106       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9107       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9108       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9109
9110       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9111       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9112       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9113       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9114       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9115     }
9116
9117     if(shCount >=5) {
9118       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9119       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9120     }
9121
9122     if(sign) {
9123       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9124       pic16_emitpcode(POC_BTFSC, 
9125                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9126       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9127     }
9128
9129     break;
9130
9131   case 6:
9132     if(same) {
9133
9134       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9135       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9136
9137       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9138       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9139       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9140       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9141       if(sign) {
9142         pic16_emitpcode(POC_BTFSC, 
9143                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9144         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9145       }
9146       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9147       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9148       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9149       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9150     } else {
9151       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9152       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9153       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9154       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9157       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9158       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9159       if(sign) {
9160         pic16_emitpcode(POC_BTFSC, 
9161                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9162         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9163       }
9164       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9166
9167         
9168     }
9169
9170     break;
9171   case 7:
9172     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9174     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9175     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9176     if(sign) {
9177       emitSKPNC;
9178       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9179     } else 
9180       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9181   }
9182 }
9183
9184
9185 /*-----------------------------------------------------------------*/
9186 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9187 /*-----------------------------------------------------------------*/
9188 static void shiftLLeftOrResult (operand *left, int offl,
9189                                 operand *result, int offr, int shCount)
9190 {
9191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9192
9193     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9194     /* shift left accumulator */
9195     AccLsh(shCount);
9196     /* or with result */
9197     /* back to result */
9198     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9199 }
9200
9201 /*-----------------------------------------------------------------*/
9202 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9203 /*-----------------------------------------------------------------*/
9204 static void shiftRLeftOrResult (operand *left, int offl,
9205                                 operand *result, int offr, int shCount)
9206 {
9207     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9208     
9209     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9210     /* shift right accumulator */
9211     AccRsh(shCount, 1);
9212     /* or with result */
9213     /* back to result */
9214     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9215 }
9216
9217 /*-----------------------------------------------------------------*/
9218 /* genlshOne - left shift a one byte quantity by known count       */
9219 /*-----------------------------------------------------------------*/
9220 static void genlshOne (operand *result, operand *left, int shCount)
9221 {       
9222     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9223     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9224 }
9225
9226 /*-----------------------------------------------------------------*/
9227 /* genlshTwo - left shift two bytes by known amount != 0           */
9228 /*-----------------------------------------------------------------*/
9229 static void genlshTwo (operand *result,operand *left, int shCount)
9230 {
9231     int size;
9232     
9233     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9234     size = pic16_getDataSize(result);
9235
9236     /* if shCount >= 8 */
9237     if (shCount >= 8) {
9238         shCount -= 8 ;
9239
9240         if (size > 1){
9241             if (shCount)
9242                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9243             else 
9244                 movLeft2Result(left, LSB, result, MSB16);
9245         }
9246         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9247     }
9248
9249     /*  1 <= shCount <= 7 */
9250     else {  
9251         if(size == 1)
9252             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9253         else 
9254             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9255     }
9256 }
9257
9258 /*-----------------------------------------------------------------*/
9259 /* shiftLLong - shift left one long from left to result            */
9260 /* offr = LSB or MSB16                                             */
9261 /*-----------------------------------------------------------------*/
9262 static void shiftLLong (operand *left, operand *result, int offr )
9263 {
9264     int size = AOP_SIZE(result);
9265     int same = pic16_sameRegs(AOP(left),AOP(result));
9266         int i;
9267
9268     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9269
9270         if (same && (offr == MSB16)) { //shift one byte
9271                 for(i=size-1;i>=MSB16;i--) {
9272                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9273                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9274                 }
9275         } else {
9276                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9277         }
9278         
9279     if (size > LSB+offr ){
9280                 if (same) {
9281                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9282                 } else {
9283                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9284                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9285                 }
9286          }
9287
9288     if(size > MSB16+offr){
9289                 if (same) {
9290                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9291                 } else {
9292                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9293                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9294                 }
9295     }
9296
9297     if(size > MSB24+offr){
9298                 if (same) {
9299                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9300                 } else {
9301                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9302                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9303                 }
9304     }
9305
9306     if(size > MSB32+offr){
9307                 if (same) {
9308                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9309                 } else {
9310                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9311                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9312                 }
9313     }
9314     if(offr != LSB)
9315                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9316
9317 }
9318
9319 /*-----------------------------------------------------------------*/
9320 /* genlshFour - shift four byte by a known amount != 0             */
9321 /*-----------------------------------------------------------------*/
9322 static void genlshFour (operand *result, operand *left, int shCount)
9323 {
9324     int size;
9325
9326     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9327     size = AOP_SIZE(result);
9328
9329     /* if shifting more that 3 bytes */
9330     if (shCount >= 24 ) {
9331         shCount -= 24;
9332         if (shCount)
9333             /* lowest order of left goes to the highest
9334             order of the destination */
9335             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9336         else
9337             movLeft2Result(left, LSB, result, MSB32);
9338
9339                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9340                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9341                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9342
9343         return;
9344     }
9345
9346     /* more than two bytes */
9347     else if ( shCount >= 16 ) {
9348         /* lower order two bytes goes to higher order two bytes */
9349         shCount -= 16;
9350         /* if some more remaining */
9351         if (shCount)
9352             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9353         else {
9354             movLeft2Result(left, MSB16, result, MSB32);
9355             movLeft2Result(left, LSB, result, MSB24);
9356         }
9357                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9358                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9359         return;
9360     }    
9361
9362     /* if more than 1 byte */
9363     else if ( shCount >= 8 ) {
9364         /* lower order three bytes goes to higher order  three bytes */
9365         shCount -= 8;
9366         if(size == 2){
9367             if(shCount)
9368                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9369             else
9370                 movLeft2Result(left, LSB, result, MSB16);
9371         }
9372         else{   /* size = 4 */
9373             if(shCount == 0){
9374                 movLeft2Result(left, MSB24, result, MSB32);
9375                 movLeft2Result(left, MSB16, result, MSB24);
9376                 movLeft2Result(left, LSB, result, MSB16);
9377                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9378             }
9379             else if(shCount == 1)
9380                 shiftLLong(left, result, MSB16);
9381             else{
9382                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9383                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9384                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9385                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9386             }
9387         }
9388     }
9389
9390     /* 1 <= shCount <= 7 */
9391     else if(shCount <= 3)
9392     { 
9393         shiftLLong(left, result, LSB);
9394         while(--shCount >= 1)
9395             shiftLLong(result, result, LSB);
9396     }
9397     /* 3 <= shCount <= 7, optimize */
9398     else{
9399         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9400         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9401         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9402     }
9403 }
9404
9405 /*-----------------------------------------------------------------*/
9406 /* genLeftShiftLiteral - left shifting by known count              */
9407 /*-----------------------------------------------------------------*/
9408 void pic16_genLeftShiftLiteral (operand *left,
9409                                  operand *right,
9410                                  operand *result,
9411                                  iCode *ic)
9412 {    
9413     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9414     int size;
9415
9416     FENTRY;
9417     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9418     pic16_freeAsmop(right,NULL,ic,TRUE);
9419
9420     pic16_aopOp(left,ic,FALSE);
9421     pic16_aopOp(result,ic,TRUE);
9422
9423     size = getSize(operandType(result));
9424
9425 #if VIEW_SIZE
9426     pic16_emitcode("; shift left ","result %d, left %d",size,
9427              AOP_SIZE(left));
9428 #endif
9429
9430     /* I suppose that the left size >= result size */
9431     if(shCount == 0){
9432         while(size--){
9433             movLeft2Result(left, size, result, size);
9434         }
9435     }
9436
9437     else if(shCount >= (size * 8))
9438         while(size--)
9439             pic16_aopPut(AOP(result),zero,size);
9440     else{
9441         switch (size) {
9442             case 1:
9443                 genlshOne (result,left,shCount);
9444                 break;
9445
9446             case 2:
9447             case 3:
9448                 genlshTwo (result,left,shCount);
9449                 break;
9450
9451             case 4:
9452                 genlshFour (result,left,shCount);
9453                 break;
9454         }
9455     }
9456     pic16_freeAsmop(left,NULL,ic,TRUE);
9457     pic16_freeAsmop(result,NULL,ic,TRUE);
9458 }
9459
9460 /*-----------------------------------------------------------------*
9461  * genMultiAsm - repeat assembly instruction for size of register.
9462  * if endian == 1, then the high byte (i.e base address + size of 
9463  * register) is used first else the low byte is used first;
9464  *-----------------------------------------------------------------*/
9465 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9466 {
9467
9468   int offset = 0;
9469
9470   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9471
9472   if(!reg)
9473     return;
9474
9475   if(!endian) {
9476     endian = 1;
9477   } else {
9478     endian = -1;
9479     offset = size-1;
9480   }
9481
9482   while(size--) {
9483     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9484     offset += endian;
9485   }
9486
9487 }
9488
9489 #if !(USE_GENERIC_SIGNED_SHIFT)
9490 /*-----------------------------------------------------------------*/
9491 /* genLeftShift - generates code for left shifting                 */
9492 /*-----------------------------------------------------------------*/
9493 static void genLeftShift (iCode *ic)
9494 {
9495   operand *left,*right, *result;
9496   int size, offset;
9497 //  char *l;
9498   symbol *tlbl , *tlbl1;
9499   pCodeOp *pctemp;
9500
9501   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9502
9503   right = IC_RIGHT(ic);
9504   left  = IC_LEFT(ic);
9505   result = IC_RESULT(ic);
9506
9507   pic16_aopOp(right,ic,FALSE);
9508
9509   /* if the shift count is known then do it 
9510      as efficiently as possible */
9511   if (AOP_TYPE(right) == AOP_LIT) {
9512     pic16_genLeftShiftLiteral (left,right,result,ic);
9513     return ;
9514   }
9515
9516   /* shift count is unknown then we have to form
9517    * a loop. Get the loop count in WREG : Note: we take
9518    * only the lower order byte since shifting
9519    * more than 32 bits make no sense anyway, ( the
9520    * largest size of an object can be only 32 bits ) */
9521   
9522   pic16_aopOp(left,ic,FALSE);
9523   pic16_aopOp(result,ic,FALSE);
9524
9525   /* now move the left to the result if they are not the
9526    * same, and if size > 1,
9527    * and if right is not same to result (!!!) -- VR */
9528   if (!pic16_sameRegs(AOP(left),AOP(result))
9529       && (AOP_SIZE(result) > 1)) {
9530
9531     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9532
9533     size = AOP_SIZE(result);
9534     offset=0;
9535     while (size--) {
9536
9537 #if 0
9538       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9539       if (*l == '@' && (IS_AOP_PREG(result))) {
9540
9541           pic16_emitcode("mov","a,%s",l);
9542           pic16_aopPut(AOP(result),"a",offset);
9543       } else
9544 #endif
9545       {
9546         /* we don't know if left is a literal or a register, take care -- VR */
9547         mov2f(AOP(result), AOP(left), offset);
9548       }
9549       offset++;
9550     }
9551   }
9552
9553   size = AOP_SIZE(result);
9554
9555   /* if it is only one byte then */
9556   if (size == 1) {
9557     if(optimized_for_speed) {
9558       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9559       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9560       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9561       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9562       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9563       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9564       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9565       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9566       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9567       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9568       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9569       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9570     } else {
9571
9572       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9573
9574       tlbl = newiTempLabel(NULL);
9575
9576 #if 1
9577       /* this is already done, why change it? */
9578       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9579                 mov2f(AOP(result), AOP(left), 0);
9580       }
9581 #endif
9582
9583       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9584       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9585       pic16_emitpLabel(tlbl->key);
9586       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9587       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9588       emitSKPC;
9589       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9590     }
9591     goto release ;
9592   }
9593     
9594   if (pic16_sameRegs(AOP(left),AOP(result))) {
9595
9596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9597     
9598     tlbl = newiTempLabel(NULL);
9599     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9600     genMultiAsm(POC_RRCF, result, size,1);
9601     pic16_emitpLabel(tlbl->key);
9602     genMultiAsm(POC_RLCF, result, size,0);
9603     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9604     emitSKPC;
9605     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9606     goto release;
9607   }
9608
9609   //tlbl = newiTempLabel(NULL);
9610   //offset = 0 ;   
9611   //tlbl1 = newiTempLabel(NULL);
9612
9613   //reAdjustPreg(AOP(result));    
9614     
9615   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9616   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9617   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9618   //MOVA(l);
9619   //pic16_emitcode("add","a,acc");         
9620   //pic16_aopPut(AOP(result),"a",offset++);
9621   //while (--size) {
9622   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9623   //  MOVA(l);
9624   //  pic16_emitcode("rlc","a");         
9625   //  pic16_aopPut(AOP(result),"a",offset++);
9626   //}
9627   //reAdjustPreg(AOP(result));
9628
9629   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9630   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9631
9632
9633   tlbl = newiTempLabel(NULL);
9634   tlbl1= newiTempLabel(NULL);
9635
9636   size = AOP_SIZE(result);
9637   offset = 1;
9638
9639   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9640
9641   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9642
9643   /* offset should be 0, 1 or 3 */
9644   
9645   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9646   emitSKPNZ;
9647   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9648
9649   pic16_emitpcode(POC_MOVWF, pctemp);
9650
9651
9652   pic16_emitpLabel(tlbl->key);
9653
9654   emitCLRC;
9655   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9656   while(--size)
9657     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9658
9659   pic16_emitpcode(POC_DECFSZ,  pctemp);
9660   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9661   pic16_emitpLabel(tlbl1->key);
9662
9663   pic16_popReleaseTempReg(pctemp,1);
9664
9665
9666  release:
9667   pic16_freeAsmop (right,NULL,ic,TRUE);
9668   pic16_freeAsmop(left,NULL,ic,TRUE);
9669   pic16_freeAsmop(result,NULL,ic,TRUE);
9670 }
9671 #endif
9672
9673
9674 #if 0
9675 #error old code (left here for reference)
9676 /*-----------------------------------------------------------------*/
9677 /* genLeftShift - generates code for left shifting                 */
9678 /*-----------------------------------------------------------------*/
9679 static void genLeftShift (iCode *ic)
9680 {
9681   operand *left,*right, *result;
9682   int size, offset;
9683   char *l;
9684   symbol *tlbl , *tlbl1;
9685   pCodeOp *pctemp;
9686
9687   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9688
9689   right = IC_RIGHT(ic);
9690   left  = IC_LEFT(ic);
9691   result = IC_RESULT(ic);
9692
9693   pic16_aopOp(right,ic,FALSE);
9694
9695   /* if the shift count is known then do it 
9696      as efficiently as possible */
9697   if (AOP_TYPE(right) == AOP_LIT) {
9698     pic16_genLeftShiftLiteral (left,right,result,ic);
9699     return ;
9700   }
9701
9702   /* shift count is unknown then we have to form 
9703      a loop get the loop count in B : Note: we take
9704      only the lower order byte since shifting
9705      more that 32 bits make no sense anyway, ( the
9706      largest size of an object can be only 32 bits ) */  
9707
9708     
9709   pic16_aopOp(left,ic,FALSE);
9710   pic16_aopOp(result,ic,FALSE);
9711
9712   /* now move the left to the result if they are not the
9713      same */
9714   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9715       AOP_SIZE(result) > 1) {
9716
9717     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9718
9719     size = AOP_SIZE(result);
9720     offset=0;
9721     while (size--) {
9722       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9723       if (*l == '@' && (IS_AOP_PREG(result))) {
9724
9725         pic16_emitcode("mov","a,%s",l);
9726         pic16_aopPut(AOP(result),"a",offset);
9727       } else {
9728
9729         /* we don't know if left is a literal or a register, take care -- VR */
9730         mov2f(AOP(result), AOP(left), offset);
9731       }
9732       offset++;
9733     }
9734   }
9735
9736   size = AOP_SIZE(result);
9737
9738   /* if it is only one byte then */
9739   if (size == 1) {
9740     if(optimized_for_speed) {
9741       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9742       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9743       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9744       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9745       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9746       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9747       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9748       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9749       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9750       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9751       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9752       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9753     } else {
9754
9755       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9756
9757       tlbl = newiTempLabel(NULL);
9758       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9759                 mov2f(AOP(result), AOP(left), 0);
9760                 
9761 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9762 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9763       }
9764
9765       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9766       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9767       pic16_emitpLabel(tlbl->key);
9768       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9769       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9770       emitSKPC;
9771       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9772     }
9773     goto release ;
9774   }
9775     
9776   if (pic16_sameRegs(AOP(left),AOP(result))) {
9777
9778     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9779     
9780     tlbl = newiTempLabel(NULL);
9781     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9782     genMultiAsm(POC_RRCF, result, size,1);
9783     pic16_emitpLabel(tlbl->key);
9784     genMultiAsm(POC_RLCF, result, size,0);
9785     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9786     emitSKPC;
9787     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9788     goto release;
9789   }
9790
9791   //tlbl = newiTempLabel(NULL);
9792   //offset = 0 ;   
9793   //tlbl1 = newiTempLabel(NULL);
9794
9795   //reAdjustPreg(AOP(result));    
9796     
9797   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9798   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9799   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9800   //MOVA(l);
9801   //pic16_emitcode("add","a,acc");         
9802   //pic16_aopPut(AOP(result),"a",offset++);
9803   //while (--size) {
9804   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9805   //  MOVA(l);
9806   //  pic16_emitcode("rlc","a");         
9807   //  pic16_aopPut(AOP(result),"a",offset++);
9808   //}
9809   //reAdjustPreg(AOP(result));
9810
9811   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9812   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9813
9814
9815   tlbl = newiTempLabel(NULL);
9816   tlbl1= newiTempLabel(NULL);
9817
9818   size = AOP_SIZE(result);
9819   offset = 1;
9820
9821   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9822
9823   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9824
9825   /* offset should be 0, 1 or 3 */
9826   
9827   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9828   emitSKPNZ;
9829   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9830
9831   pic16_emitpcode(POC_MOVWF, pctemp);
9832
9833
9834   pic16_emitpLabel(tlbl->key);
9835
9836   emitCLRC;
9837   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9838   while(--size)
9839     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9840
9841   pic16_emitpcode(POC_DECFSZ,  pctemp);
9842   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9843   pic16_emitpLabel(tlbl1->key);
9844
9845   pic16_popReleaseTempReg(pctemp,1);
9846
9847
9848  release:
9849   pic16_freeAsmop (right,NULL,ic,TRUE);
9850   pic16_freeAsmop(left,NULL,ic,TRUE);
9851   pic16_freeAsmop(result,NULL,ic,TRUE);
9852 }
9853 #endif
9854
9855 /*-----------------------------------------------------------------*/
9856 /* genrshOne - right shift a one byte quantity by known count      */
9857 /*-----------------------------------------------------------------*/
9858 static void genrshOne (operand *result, operand *left,
9859                        int shCount, int sign)
9860 {
9861     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9862     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9863 }
9864
9865 /*-----------------------------------------------------------------*/
9866 /* genrshTwo - right shift two bytes by known amount != 0          */
9867 /*-----------------------------------------------------------------*/
9868 static void genrshTwo (operand *result,operand *left,
9869                        int shCount, int sign)
9870 {
9871   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9872   /* if shCount >= 8 */
9873   if (shCount >= 8) {
9874     shCount -= 8 ;
9875     if (shCount)
9876       shiftR1Left2Result(left, MSB16, result, LSB,
9877                          shCount, sign);
9878     else
9879       movLeft2Result(left, MSB16, result, LSB);
9880
9881     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9882
9883     if(sign) {
9884       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9885       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9886     }
9887   }
9888
9889   /*  1 <= shCount <= 7 */
9890   else
9891     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9892 }
9893
9894 /*-----------------------------------------------------------------*/
9895 /* shiftRLong - shift right one long from left to result           */
9896 /* offl = LSB or MSB16                                             */
9897 /*-----------------------------------------------------------------*/
9898 static void shiftRLong (operand *left, int offl,
9899                         operand *result, int sign)
9900 {
9901     int size = AOP_SIZE(result);
9902     int same = pic16_sameRegs(AOP(left),AOP(result));
9903     int i;
9904     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9905
9906         if (same && (offl == MSB16)) { //shift one byte right
9907                 for(i=MSB16;i<size;i++) {
9908                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9909                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9910                 }
9911         }
9912
9913     if(sign)
9914                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9915         else
9916                 emitCLRC;
9917
9918         if (same) {
9919                 if (offl == LSB)
9920                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9921         } else {
9922         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9923         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9924         }
9925
9926     if(offl == MSB16) {
9927         /* add sign of "a" */
9928         pic16_addSign(result, MSB32, sign);
9929         }
9930
9931         if (same) {
9932         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9933         } else {
9934         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9935         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9936         }
9937         
9938         if (same) {
9939         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9940         } else {
9941         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9942         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9943         }
9944
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9947         } else {
9948         if(offl == LSB){
9949                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9950                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9951         }
9952         }
9953 }
9954
9955 /*-----------------------------------------------------------------*/
9956 /* genrshFour - shift four byte by a known amount != 0             */
9957 /*-----------------------------------------------------------------*/
9958 static void genrshFour (operand *result, operand *left,
9959                         int shCount, int sign)
9960 {
9961   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9962   /* if shifting more that 3 bytes */
9963   if(shCount >= 24 ) {
9964     shCount -= 24;
9965     if(shCount)
9966       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9967     else
9968       movLeft2Result(left, MSB32, result, LSB);
9969
9970     pic16_addSign(result, MSB16, sign);
9971   }
9972   else if(shCount >= 16){
9973     shCount -= 16;
9974     if(shCount)
9975       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9976     else{
9977       movLeft2Result(left, MSB24, result, LSB);
9978       movLeft2Result(left, MSB32, result, MSB16);
9979     }
9980     pic16_addSign(result, MSB24, sign);
9981   }
9982   else if(shCount >= 8){
9983     shCount -= 8;
9984     if(shCount == 1)
9985       shiftRLong(left, MSB16, result, sign);
9986     else if(shCount == 0){
9987       movLeft2Result(left, MSB16, result, LSB);
9988       movLeft2Result(left, MSB24, result, MSB16);
9989       movLeft2Result(left, MSB32, result, MSB24);
9990       pic16_addSign(result, MSB32, sign);
9991     }
9992     else{ //shcount >= 2
9993       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9994       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9995       /* the last shift is signed */
9996       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9997       pic16_addSign(result, MSB32, sign);
9998     }
9999   }
10000   else{   /* 1 <= shCount <= 7 */
10001     if(shCount <= 2){
10002       shiftRLong(left, LSB, result, sign);
10003       if(shCount == 2)
10004         shiftRLong(result, LSB, result, sign);
10005     }
10006     else{
10007       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10008       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10009       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10010     }
10011   }
10012 }
10013
10014 /*-----------------------------------------------------------------*/
10015 /* genRightShiftLiteral - right shifting by known count            */
10016 /*-----------------------------------------------------------------*/
10017 static void genRightShiftLiteral (operand *left,
10018                                   operand *right,
10019                                   operand *result,
10020                                   iCode *ic,
10021                                   int sign)
10022 {    
10023   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10024   int lsize,res_size;
10025
10026   pic16_freeAsmop(right,NULL,ic,TRUE);
10027
10028   pic16_aopOp(left,ic,FALSE);
10029   pic16_aopOp(result,ic,TRUE);
10030
10031   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10032
10033 #if VIEW_SIZE
10034   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10035                  AOP_SIZE(left));
10036 #endif
10037
10038   lsize = pic16_getDataSize(left);
10039   res_size = pic16_getDataSize(result);
10040   /* test the LEFT size !!! */
10041
10042   /* I suppose that the left size >= result size */
10043   if(shCount == 0){
10044     assert (res_size <= lsize);
10045     while (res_size--) {
10046       mov2f (AOP(result), AOP(left), res_size);
10047     } // for
10048   }
10049
10050   else if(shCount >= (lsize * 8)){
10051
10052     if(res_size == 1) {
10053       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10054       if(sign) {
10055         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10056         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10057       }
10058     } else {
10059
10060       if(sign) {
10061         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10062         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10064         while(res_size--)
10065           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10066
10067       } else {
10068
10069         while(res_size--)
10070           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10071       }
10072     }
10073   } else {
10074
10075     switch (res_size) {
10076     case 1:
10077       genrshOne (result,left,shCount,sign);
10078       break;
10079
10080     case 2:
10081       genrshTwo (result,left,shCount,sign);
10082       break;
10083
10084     case 4:
10085       genrshFour (result,left,shCount,sign);
10086       break;
10087     default :
10088       break;
10089     }
10090
10091   }
10092
10093   pic16_freeAsmop(left,NULL,ic,TRUE);
10094   pic16_freeAsmop(result,NULL,ic,TRUE);
10095 }
10096
10097 #if !(USE_GENERIC_SIGNED_SHIFT)
10098 /*-----------------------------------------------------------------*/
10099 /* genSignedRightShift - right shift of signed number              */
10100 /*-----------------------------------------------------------------*/
10101 static void genSignedRightShift (iCode *ic)
10102 {
10103   operand *right, *left, *result;
10104   int size, offset;
10105   //  char *l;
10106   symbol *tlbl, *tlbl1 ;
10107   pCodeOp *pctemp;
10108
10109   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10110
10111   /* we do it the hard way put the shift count in b
10112      and loop thru preserving the sign */
10113   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10114
10115   right = IC_RIGHT(ic);
10116   left  = IC_LEFT(ic);
10117   result = IC_RESULT(ic);
10118
10119   pic16_aopOp(right,ic,FALSE);  
10120   pic16_aopOp(left,ic,FALSE);
10121   pic16_aopOp(result,ic,FALSE);
10122
10123
10124   if ( AOP_TYPE(right) == AOP_LIT) {
10125     genRightShiftLiteral (left,right,result,ic,1);
10126     return ;
10127   }
10128   /* shift count is unknown then we have to form 
10129      a loop get the loop count in B : Note: we take
10130      only the lower order byte since shifting
10131      more that 32 bits make no sense anyway, ( the
10132      largest size of an object can be only 32 bits ) */  
10133
10134   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10135   //pic16_emitcode("inc","b");
10136   //pic16_freeAsmop (right,NULL,ic,TRUE);
10137   //pic16_aopOp(left,ic,FALSE);
10138   //pic16_aopOp(result,ic,FALSE);
10139
10140   /* now move the left to the result if they are not the
10141      same */
10142   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10143       AOP_SIZE(result) > 1) {
10144
10145     size = AOP_SIZE(result);
10146     offset=0;
10147     while (size--) { 
10148       /*
10149         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10150         if (*l == '@' && IS_AOP_PREG(result)) {
10151
10152         pic16_emitcode("mov","a,%s",l);
10153         pic16_aopPut(AOP(result),"a",offset);
10154         } else
10155         pic16_aopPut(AOP(result),l,offset);
10156       */
10157       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10158       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10159
10160       offset++;
10161     }
10162   }
10163
10164   /* mov the highest order bit to OVR */    
10165   tlbl = newiTempLabel(NULL);
10166   tlbl1= newiTempLabel(NULL);
10167
10168   size = AOP_SIZE(result);
10169   offset = size - 1;
10170
10171   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10172
10173   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10174
10175   /* offset should be 0, 1 or 3 */
10176   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10177   emitSKPNZ;
10178   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10179
10180   pic16_emitpcode(POC_MOVWF, pctemp);
10181
10182
10183   pic16_emitpLabel(tlbl->key);
10184
10185   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10186   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10187
10188   while(--size) {
10189     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10190   }
10191
10192   pic16_emitpcode(POC_DECFSZ,  pctemp);
10193   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10194   pic16_emitpLabel(tlbl1->key);
10195
10196   pic16_popReleaseTempReg(pctemp,1);
10197 #if 0
10198   size = AOP_SIZE(result);
10199   offset = size - 1;
10200   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10201   pic16_emitcode("rlc","a");
10202   pic16_emitcode("mov","ov,c");
10203   /* if it is only one byte then */
10204   if (size == 1) {
10205     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10206     MOVA(l);
10207     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10208     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10209     pic16_emitcode("mov","c,ov");
10210     pic16_emitcode("rrc","a");
10211     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10212     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10213     pic16_aopPut(AOP(result),"a",0);
10214     goto release ;
10215   }
10216
10217   reAdjustPreg(AOP(result));
10218   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10219   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10220   pic16_emitcode("mov","c,ov");
10221   while (size--) {
10222     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10223     MOVA(l);
10224     pic16_emitcode("rrc","a");         
10225     pic16_aopPut(AOP(result),"a",offset--);
10226   }
10227   reAdjustPreg(AOP(result));
10228   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10229   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10230
10231  release:
10232 #endif
10233
10234   pic16_freeAsmop(left,NULL,ic,TRUE);
10235   pic16_freeAsmop(result,NULL,ic,TRUE);
10236   pic16_freeAsmop(right,NULL,ic,TRUE);
10237 }
10238 #endif
10239
10240 #if !(USE_GENERIC_SIGNED_SHIFT)
10241 #warning This implementation of genRightShift() is incomplete!
10242 /*-----------------------------------------------------------------*/
10243 /* genRightShift - generate code for right shifting                */
10244 /*-----------------------------------------------------------------*/
10245 static void genRightShift (iCode *ic)
10246 {
10247     operand *right, *left, *result;
10248     sym_link *letype ;
10249     int size, offset;
10250     char *l;
10251     symbol *tlbl, *tlbl1 ;
10252
10253     /* if signed then we do it the hard way preserve the
10254     sign bit moving it inwards */
10255     letype = getSpec(operandType(IC_LEFT(ic)));
10256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10257
10258     if (!SPEC_USIGN(letype)) {
10259         genSignedRightShift (ic);
10260         return ;
10261     }
10262
10263     /* signed & unsigned types are treated the same : i.e. the
10264     signed is NOT propagated inwards : quoting from the
10265     ANSI - standard : "for E1 >> E2, is equivalent to division
10266     by 2**E2 if unsigned or if it has a non-negative value,
10267     otherwise the result is implementation defined ", MY definition
10268     is that the sign does not get propagated */
10269
10270     right = IC_RIGHT(ic);
10271     left  = IC_LEFT(ic);
10272     result = IC_RESULT(ic);
10273
10274     pic16_aopOp(right,ic,FALSE);
10275
10276     /* if the shift count is known then do it 
10277     as efficiently as possible */
10278     if (AOP_TYPE(right) == AOP_LIT) {
10279         genRightShiftLiteral (left,right,result,ic, 0);
10280         return ;
10281     }
10282
10283     /* shift count is unknown then we have to form 
10284     a loop get the loop count in B : Note: we take
10285     only the lower order byte since shifting
10286     more that 32 bits make no sense anyway, ( the
10287     largest size of an object can be only 32 bits ) */  
10288
10289     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10290     pic16_emitcode("inc","b");
10291     pic16_aopOp(left,ic,FALSE);
10292     pic16_aopOp(result,ic,FALSE);
10293
10294     /* now move the left to the result if they are not the
10295     same */
10296     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10297         AOP_SIZE(result) > 1) {
10298
10299         size = AOP_SIZE(result);
10300         offset=0;
10301         while (size--) {
10302             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10303             if (*l == '@' && IS_AOP_PREG(result)) {
10304
10305                 pic16_emitcode("mov","a,%s",l);
10306                 pic16_aopPut(AOP(result),"a",offset);
10307             } else
10308                 pic16_aopPut(AOP(result),l,offset);
10309             offset++;
10310         }
10311     }
10312
10313     tlbl = newiTempLabel(NULL);
10314     tlbl1= newiTempLabel(NULL);
10315     size = AOP_SIZE(result);
10316     offset = size - 1;
10317
10318     /* if it is only one byte then */
10319     if (size == 1) {
10320
10321       tlbl = newiTempLabel(NULL);
10322       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10323         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10324         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10325       }
10326
10327       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10328       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10329       pic16_emitpLabel(tlbl->key);
10330       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10331       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10332       emitSKPC;
10333       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10334
10335       goto release ;
10336     }
10337
10338     reAdjustPreg(AOP(result));
10339     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10340     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10341     CLRC;
10342     while (size--) {
10343         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10344         MOVA(l);
10345         pic16_emitcode("rrc","a");         
10346         pic16_aopPut(AOP(result),"a",offset--);
10347     }
10348     reAdjustPreg(AOP(result));
10349
10350     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10351     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10352
10353 release:
10354     pic16_freeAsmop(left,NULL,ic,TRUE);
10355     pic16_freeAsmop (right,NULL,ic,TRUE);
10356     pic16_freeAsmop(result,NULL,ic,TRUE);
10357 }
10358 #endif
10359
10360 #if (USE_GENERIC_SIGNED_SHIFT)
10361 /*-----------------------------------------------------------------*/
10362 /* genGenericShift - generates code for left or right shifting     */
10363 /*-----------------------------------------------------------------*/
10364 static void genGenericShift (iCode *ic, int isShiftLeft) {
10365   operand *left,*right, *result;
10366   int offset;
10367   int sign, signedCount;
10368   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10369   PIC_OPCODE pos_shift, neg_shift;
10370
10371   FENTRY;
10372
10373   right = IC_RIGHT(ic);
10374   left  = IC_LEFT(ic);
10375   result = IC_RESULT(ic);
10376
10377   pic16_aopOp(right,ic,FALSE);
10378   pic16_aopOp(left,ic,FALSE);
10379   pic16_aopOp(result,ic,TRUE);
10380
10381   sign = !SPEC_USIGN(operandType (left));
10382   signedCount = !SPEC_USIGN(operandType (right));
10383
10384   /* if the shift count is known then do it 
10385      as efficiently as possible */
10386   if (AOP_TYPE(right) == AOP_LIT) {
10387     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10388     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10389     // we should modify right->aopu.aop_lit here!
10390     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10391     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10392     if (isShiftLeft)
10393       pic16_genLeftShiftLiteral (left,right,result,ic);
10394     else
10395       genRightShiftLiteral (left,right,result,ic, sign);
10396
10397     goto release;
10398   } // if (right is literal)
10399
10400   /* shift count is unknown then we have to form a loop.
10401    * Note: we take only the lower order byte since shifting
10402    * more than 32 bits make no sense anyway, ( the
10403    * largest size of an object can be only 32 bits )
10404    * Note: we perform arithmetic shifts if the left operand is
10405    * signed and we do an (effective) right shift, i. e. we
10406    * shift in the sign bit from the left. */
10407    
10408   label_complete = newiTempLabel ( NULL );
10409   label_loop_pos = newiTempLabel ( NULL );
10410   label_loop_neg = NULL;
10411   label_negative = NULL;
10412   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10413   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10414
10415   if (signedCount) {
10416     // additional labels needed
10417     label_loop_neg = newiTempLabel ( NULL );
10418     label_negative = newiTempLabel ( NULL );
10419   } // if
10420
10421   // copy source to result -- this will effectively truncate the left operand to the size of result!
10422   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10423   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10424   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10425     mov2f (AOP(result),AOP(left), offset);
10426   } // for
10427
10428   // if result is longer than left, fill with zeros (or sign)
10429   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10430     if (sign && AOP_SIZE(left) > 0) {
10431       // shift signed operand -- fill with sign
10432       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10433       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10434       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10435       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10436         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10437       } // for
10438     } else {
10439       // shift unsigned operand -- fill result with zeros
10440       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10441         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10442       } // for
10443     }
10444   } // if (size mismatch)
10445
10446   pic16_mov2w (AOP(right), 0);
10447   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10448   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10449   
10450 #if 0
10451   // perform a shift by one (shift count is positive)
10452   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10453   // 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])
10454   pic16_emitpLabel (label_loop_pos->key);
10455   emitCLRC;
10456   if (sign && (pos_shift == POC_RRCF)) {
10457     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10458     emitSETC;
10459   } // if
10460   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10461   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10462   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10463 #else
10464   // perform a shift by one (shift count is positive)
10465   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10466   // 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])
10467   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10468   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10469   emitCLRC;
10470   pic16_emitpLabel (label_loop_pos->key);
10471   if (sign && (pos_shift == POC_RRCF)) {
10472     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10473     emitSETC;
10474   } // if
10475   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10476   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10477   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10478   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10479 #endif
10480
10481   if (signedCount) {
10482     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10483
10484     pic16_emitpLabel (label_negative->key);
10485     // perform a shift by -1 (shift count is negative)
10486     // 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)
10487     emitCLRC;
10488     pic16_emitpLabel (label_loop_neg->key);
10489     if (sign && (neg_shift == POC_RRCF)) {
10490       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10491       emitSETC;
10492     } // if
10493     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10494     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10497   } // if (signedCount)
10498
10499   pic16_emitpLabel (label_complete->key);
10500
10501 release:
10502   pic16_freeAsmop (right,NULL,ic,TRUE);
10503   pic16_freeAsmop(left,NULL,ic,TRUE);
10504   pic16_freeAsmop(result,NULL,ic,TRUE);
10505 }
10506
10507 static void genLeftShift (iCode *ic) {
10508   genGenericShift (ic, 1);
10509 }
10510
10511 static void genRightShift (iCode *ic) {
10512   genGenericShift (ic, 0);
10513 }
10514 #endif
10515
10516
10517 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10518 void pic16_loadFSR0(operand *op, int lit)
10519 {
10520   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10521     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10522   } else {
10523     assert (!OP_SYMBOL(op)->remat);
10524     // set up FSR0 with address of result
10525     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10526     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10527   }
10528 }
10529
10530 /*-----------------------------------------------------------------*/
10531 /* genUnpackBits - generates code for unpacking bits               */
10532 /*-----------------------------------------------------------------*/
10533 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10534 {    
10535   int shCnt ;
10536   int rlen = 0 ;
10537   sym_link *etype, *letype;
10538   int blen=0, bstr=0;
10539   int lbstr;
10540   int offset = 0 ;
10541
10542     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10543     etype = getSpec(operandType(result));
10544     letype = getSpec(operandType(left));
10545     
10546 //    if(IS_BITFIELD(etype)) {
10547       blen = SPEC_BLEN(etype);
10548       bstr = SPEC_BSTR(etype);
10549 //    }
10550
10551     lbstr = SPEC_BSTR( letype );
10552
10553 #if 1
10554     if((blen == 1) && (bstr < 8)) {
10555       /* it is a single bit, so use the appropriate bit instructions */
10556       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10557
10558       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10559       
10560       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10561       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10562         /* workaround to reduce the extra lfsr instruction */
10563         pic16_emitpcode(POC_BTFSC,
10564               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10565       } else {
10566         pic16_loadFSR0 (left, 0);
10567         pic16_emitpcode(POC_BTFSC,
10568               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10569       }
10570         
10571       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10572
10573       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10574       return;
10575     }
10576
10577 #endif
10578
10579         /* the following call to pic16_loadFSR0 is temporary until
10580          * optimization to handle single bit assignments is added
10581          * to the function. Until then use the old safe way! -- VR */
10582
10583     if (OP_SYMBOL(left)->remat) {
10584         // access symbol directly
10585         pic16_mov2w (AOP(left), 0);
10586     } else {
10587         pic16_loadFSR0( left, 0 );
10588  
10589         /* read the first byte  */
10590         switch (ptype) {
10591                 case POINTER:
10592                 case IPOINTER:
10593                 case PPOINTER:
10594                 case FPOINTER:
10595                 case GPOINTER:
10596                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10597                         break;
10598                 case CPOINTER:
10599                         pic16_emitcode("clr","a");
10600                         pic16_emitcode("movc","a","@a+dptr");
10601                         assert (0);
10602                         break;
10603         }
10604     }
10605
10606         /* if we have bitdisplacement then it fits   */
10607         /* into this byte completely or if length is */
10608         /* less than a byte                          */
10609         if ((shCnt = SPEC_BSTR(etype)) || 
10610                 (SPEC_BLEN(etype) <= 8))  {
10611
10612                 /* shift right acc */
10613                 AccRsh(shCnt, 0);
10614
10615                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10616                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10617
10618 /* VR -- normally I would use the following, but since we use the hack,
10619  * to avoid the masking from AccRsh, why not mask it right now? */
10620
10621 /*
10622                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10623 */
10624
10625                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10626           return ;
10627         }
10628
10629
10630
10631         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10632         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10633         exit(-1);
10634
10635     /* bit field did not fit in a byte  */
10636     rlen = SPEC_BLEN(etype) - 8;
10637     pic16_aopPut(AOP(result),"a",offset++);
10638
10639     while (1)  {
10640
10641         switch (ptype) {
10642         case POINTER:
10643         case IPOINTER:
10644             pic16_emitcode("inc","%s",rname);
10645             pic16_emitcode("mov","a,@%s",rname);
10646             break;
10647             
10648         case PPOINTER:
10649             pic16_emitcode("inc","%s",rname);
10650             pic16_emitcode("movx","a,@%s",rname);
10651             break;
10652
10653         case FPOINTER:
10654             pic16_emitcode("inc","dptr");
10655             pic16_emitcode("movx","a,@dptr");
10656             break;
10657             
10658         case CPOINTER:
10659             pic16_emitcode("clr","a");
10660             pic16_emitcode("inc","dptr");
10661             pic16_emitcode("movc","a","@a+dptr");
10662             break;
10663             
10664         case GPOINTER:
10665             pic16_emitcode("inc","dptr");
10666             pic16_emitcode("lcall","__gptrget");
10667             break;
10668         }
10669
10670         rlen -= 8;            
10671         /* if we are done */
10672         if ( rlen <= 0 )
10673             break ;
10674         
10675         pic16_aopPut(AOP(result),"a",offset++);
10676                               
10677     }
10678     
10679     if (rlen) {
10680         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10681         pic16_aopPut(AOP(result),"a",offset);          
10682     }
10683     
10684     return ;
10685 }
10686
10687
10688 static void genDataPointerGet(operand *left,
10689                               operand *result,
10690                               iCode *ic)
10691 {
10692   int size, offset = 0, leoffset=0 ;
10693
10694         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10695         pic16_aopOp(result, ic, TRUE);
10696
10697         FENTRY;
10698
10699         size = AOP_SIZE(result);
10700 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10701
10702
10703 #if 0
10704         /* The following tests may save a redudant movff instruction when
10705          * accessing unions */
10706          
10707         /* if they are the same */
10708         if (operandsEqu (left, result)) {
10709                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10710                 goto release;
10711         }
10712 #endif
10713
10714 #if 0
10715         /* if they are the same registers */
10716         if (pic16_sameRegs(AOP(left),AOP(result))) {
10717                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10718                 goto release;
10719         }
10720 #endif
10721
10722 #if 1
10723         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10724                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10725                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10726                 goto release;
10727         }
10728 #endif
10729
10730
10731 #if 0
10732         if ( AOP_TYPE(left) == AOP_PCODE) {
10733                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10734                                 AOP(left)->aopu.pcop->name,
10735                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10736                                 PCOR(AOP(left)->aopu.pcop)->instance:
10737                                 PCOI(AOP(left)->aopu.pcop)->offset);
10738         }
10739 #endif
10740
10741         if(AOP(left)->aopu.pcop->type == PO_DIR)
10742                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10743
10744         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10745
10746         while (size--) {
10747                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10748                 
10749 //              pic16_DumpOp("(result)",result);
10750                 if(is_LitAOp(AOP(result))) {
10751                         pic16_mov2w(AOP(left), offset); // patch 8
10752                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10753                 } else {
10754                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10755                                 pic16_popGet(AOP(left), offset), //patch 8
10756                                 pic16_popGet(AOP(result), offset)));
10757                 }
10758
10759                 offset++;
10760                 leoffset++;
10761         }
10762
10763 release:
10764     pic16_freeAsmop(result,NULL,ic,TRUE);
10765 }
10766
10767
10768
10769 /*-----------------------------------------------------------------*/
10770 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10771 /*-----------------------------------------------------------------*/
10772 static void genNearPointerGet (operand *left, 
10773                                operand *result, 
10774                                iCode *ic)
10775 {
10776 //  asmop *aop = NULL;
10777   //regs *preg = NULL ;
10778   sym_link *rtype, *retype;
10779   sym_link *ltype = operandType(left);    
10780
10781     FENTRY;
10782     
10783     rtype = operandType(result);
10784     retype= getSpec(rtype);
10785     
10786     pic16_aopOp(left,ic,FALSE);
10787
10788 //    pic16_DumpOp("(left)",left);
10789 //    pic16_DumpOp("(result)",result);
10790
10791     /* if left is rematerialisable and
10792      * result is not bit variable type and
10793      * the left is pointer to data space i.e
10794      * lower 128 bytes of space */
10795     
10796     if (AOP_TYPE(left) == AOP_PCODE
10797       && !IS_BITFIELD(retype)
10798       && DCL_TYPE(ltype) == POINTER) {
10799
10800         genDataPointerGet (left,result,ic);
10801         pic16_freeAsmop(left, NULL, ic, TRUE);
10802         return ;
10803     }
10804     
10805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10806     pic16_aopOp (result,ic,TRUE);
10807     
10808     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10809
10810 #if 1
10811     if(IS_BITFIELD( retype )
10812       && (SPEC_BLEN(operandType(result))==1)
10813     ) {
10814       iCode *nextic;
10815       pCodeOp *jop;
10816       int bitstrt, bytestrt;
10817
10818         /* if this is bitfield of size 1, see if we are checking the value
10819          * of a single bit in an if-statement,
10820          * if yes, then don't generate usual code, but execute the
10821          * genIfx directly -- VR */
10822
10823         nextic = ic->next;
10824
10825         /* CHECK: if next iCode is IFX
10826          * and current result operand is nextic's conditional operand
10827          * and current result operand live ranges ends at nextic's key number
10828          */
10829         if((nextic->op == IFX)
10830           && (result == IC_COND(nextic))
10831           && (OP_LIVETO(result) == nextic->seq)
10832           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10833           ) {
10834             /* everything is ok then */
10835             /* find a way to optimize the genIfx iCode */
10836
10837             bytestrt = SPEC_BSTR(operandType(result))/8;
10838             bitstrt = SPEC_BSTR(operandType(result))%8;
10839             
10840             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10841
10842             genIfxpCOpJump(nextic, jop);
10843             
10844             pic16_freeAsmop(left, NULL, ic, TRUE);
10845             pic16_freeAsmop(result, NULL, ic, TRUE);
10846             return;
10847         }
10848     }
10849 #endif
10850
10851
10852     /* if the value is already in a pointer register
10853      * then don't need anything more */
10854     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
10855       /* otherwise get a free pointer register */
10856       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10857                 
10858       ;
10859     }
10860
10861     /* if bitfield then unpack the bits */
10862     if (IS_BITFIELD(retype)) 
10863       genUnpackBits (result, left, NULL, POINTER);
10864     else {
10865       /* we have can just get the values */
10866       int size = AOP_SIZE(result);
10867       int offset = 0;   
10868         
10869       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10870
10871       pic16_loadFSR0( left, 0 );
10872
10873       while(size--) {
10874         if(size) {
10875           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876                 pic16_popGet(AOP(result), offset++)));
10877         } else {
10878           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879                 pic16_popGet(AOP(result), offset++)));
10880         }
10881       }
10882     }
10883
10884 #if 0
10885     /* now some housekeeping stuff */
10886     if (aop) {
10887       /* we had to allocate for this iCode */
10888       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10889       pic16_freeAsmop(NULL,aop,ic,TRUE);
10890     } else { 
10891       /* we did not allocate which means left
10892        * already in a pointer register, then
10893        * if size > 0 && this could be used again
10894        * we have to point it back to where it 
10895        * belongs */
10896       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10897       if (AOP_SIZE(result) > 1
10898         && !OP_SYMBOL(left)->remat
10899         && ( OP_SYMBOL(left)->liveTo > ic->seq
10900             || ic->depth )) {
10901 //        int size = AOP_SIZE(result) - 1;
10902 //        while (size--)
10903 //          pic16_emitcode("dec","%s",rname);
10904         }
10905     }
10906 #endif
10907
10908     /* done */
10909     pic16_freeAsmop(left,NULL,ic,TRUE);
10910     pic16_freeAsmop(result,NULL,ic,TRUE);
10911 }
10912
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left, 
10917                                operand *result, 
10918                                iCode *ic)
10919 {
10920     asmop *aop = NULL;
10921     regs *preg = NULL ;
10922     char *rname ;
10923     sym_link *rtype, *retype;    
10924
10925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10926
10927     rtype = operandType(result);
10928     retype= getSpec(rtype);
10929     
10930     pic16_aopOp(left,ic,FALSE);
10931
10932   /* if the value is already in a pointer register
10933        then don't need anything more */
10934     if (!AOP_INPREG(AOP(left))) {
10935         /* otherwise get a free pointer register */
10936         aop = newAsmop(0);
10937         preg = getFreePtr(ic,&aop,FALSE);
10938         pic16_emitcode("mov","%s,%s",
10939                 preg->name,
10940                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941         rname = preg->name ;
10942     } else
10943         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10944     
10945     pic16_freeAsmop(left,NULL,ic,TRUE);
10946     pic16_aopOp (result,ic,TRUE);
10947
10948     /* if bitfield then unpack the bits */
10949     if (IS_BITFIELD(retype)) 
10950         genUnpackBits (result,left,rname,PPOINTER);
10951     else {
10952         /* we have can just get the values */
10953         int size = AOP_SIZE(result);
10954         int offset = 0 ;        
10955         
10956         while (size--) {
10957             
10958             pic16_emitcode("movx","a,@%s",rname);
10959             pic16_aopPut(AOP(result),"a",offset);
10960             
10961             offset++ ;
10962             
10963             if (size)
10964                 pic16_emitcode("inc","%s",rname);
10965         }
10966     }
10967
10968     /* now some housekeeping stuff */
10969     if (aop) {
10970         /* we had to allocate for this iCode */
10971         pic16_freeAsmop(NULL,aop,ic,TRUE);
10972     } else { 
10973         /* we did not allocate which means left
10974            already in a pointer register, then
10975            if size > 0 && this could be used again
10976            we have to point it back to where it 
10977            belongs */
10978         if (AOP_SIZE(result) > 1 &&
10979             !OP_SYMBOL(left)->remat &&
10980             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10981               ic->depth )) {
10982             int size = AOP_SIZE(result) - 1;
10983             while (size--)
10984                 pic16_emitcode("dec","%s",rname);
10985         }
10986     }
10987
10988     /* done */
10989     pic16_freeAsmop(result,NULL,ic,TRUE);
10990     
10991         
10992 }
10993
10994 /*-----------------------------------------------------------------*/
10995 /* genFarPointerGet - gget value from far space                    */
10996 /*-----------------------------------------------------------------*/
10997 static void genFarPointerGet (operand *left,
10998                               operand *result, iCode *ic)
10999 {
11000     int size, offset ;
11001     sym_link *retype = getSpec(operandType(result));
11002
11003     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11004
11005     pic16_aopOp(left,ic,FALSE);
11006
11007     /* if the operand is already in dptr 
11008     then we do nothing else we move the value to dptr */
11009     if (AOP_TYPE(left) != AOP_STR) {
11010         /* if this is remateriazable */
11011         if (AOP_TYPE(left) == AOP_IMMD)
11012             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11013         else { /* we need to get it byte by byte */
11014             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11015             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11016             if (options.model == MODEL_FLAT24)
11017             {
11018                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11019             }
11020         }
11021     }
11022     /* so dptr know contains the address */
11023     pic16_freeAsmop(left,NULL,ic,TRUE);
11024     pic16_aopOp(result,ic,TRUE);
11025
11026     /* if bit then unpack */
11027     if (IS_BITFIELD(retype)) 
11028         genUnpackBits(result,left,"dptr",FPOINTER);
11029     else {
11030         size = AOP_SIZE(result);
11031         offset = 0 ;
11032
11033         while (size--) {
11034             pic16_emitcode("movx","a,@dptr");
11035             pic16_aopPut(AOP(result),"a",offset++);
11036             if (size)
11037                 pic16_emitcode("inc","dptr");
11038         }
11039     }
11040
11041     pic16_freeAsmop(result,NULL,ic,TRUE);
11042 }
11043
11044 #if 0
11045 /*-----------------------------------------------------------------*/
11046 /* genCodePointerGet - get value from code space                  */
11047 /*-----------------------------------------------------------------*/
11048 static void genCodePointerGet (operand *left,
11049                                 operand *result, iCode *ic)
11050 {
11051     int size, offset ;
11052     sym_link *retype = getSpec(operandType(result));
11053
11054     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11055
11056     pic16_aopOp(left,ic,FALSE);
11057
11058     /* if the operand is already in dptr 
11059     then we do nothing else we move the value to dptr */
11060     if (AOP_TYPE(left) != AOP_STR) {
11061         /* if this is remateriazable */
11062         if (AOP_TYPE(left) == AOP_IMMD)
11063             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11064         else { /* we need to get it byte by byte */
11065             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11066             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11067             if (options.model == MODEL_FLAT24)
11068             {
11069                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11070             }
11071         }
11072     }
11073     /* so dptr know contains the address */
11074     pic16_freeAsmop(left,NULL,ic,TRUE);
11075     pic16_aopOp(result,ic,FALSE);
11076
11077     /* if bit then unpack */
11078     if (IS_BITFIELD(retype)) 
11079         genUnpackBits(result,left,"dptr",CPOINTER);
11080     else {
11081         size = AOP_SIZE(result);
11082         offset = 0 ;
11083
11084         while (size--) {
11085             pic16_emitcode("clr","a");
11086             pic16_emitcode("movc","a,@a+dptr");
11087             pic16_aopPut(AOP(result),"a",offset++);
11088             if (size)
11089                 pic16_emitcode("inc","dptr");
11090         }
11091     }
11092
11093     pic16_freeAsmop(result,NULL,ic,TRUE);
11094 }
11095 #endif
11096
11097 #if 0
11098 /*-----------------------------------------------------------------*/
11099 /* genGenPointerGet - gget value from generic pointer space        */
11100 /*-----------------------------------------------------------------*/
11101 static void genGenPointerGet (operand *left,
11102                               operand *result, iCode *ic)
11103 {
11104   int size, offset, lit;
11105   sym_link *retype = getSpec(operandType(result));
11106
11107         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11108         pic16_aopOp(left,ic,FALSE);
11109         pic16_aopOp(result,ic,FALSE);
11110         size = AOP_SIZE(result);
11111
11112         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11113
11114         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11115
11116                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11117                 // load FSR0 from immediate
11118                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11119
11120 //              pic16_loadFSR0( left );
11121
11122                 offset = 0;
11123                 while(size--) {
11124                         if(size) {
11125                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11126                         } else {
11127                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11128                         }
11129                         offset++;
11130                 }
11131                 goto release;
11132
11133         }
11134         else { /* we need to get it byte by byte */
11135                 // set up FSR0 with address from left
11136                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11137                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11138                 
11139                 offset = 0 ;
11140
11141                 while(size--) {
11142                         if(size) {
11143                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11144                         } else {
11145                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11146                         }
11147                         offset++;
11148                 }
11149                 goto release;
11150         }
11151
11152   /* if bit then unpack */
11153         if (IS_BITFIELD(retype)) 
11154                 genUnpackBits(result,left,"BAD",GPOINTER);
11155
11156         release:
11157         pic16_freeAsmop(left,NULL,ic,TRUE);
11158         pic16_freeAsmop(result,NULL,ic,TRUE);
11159
11160 }
11161 #endif
11162
11163
11164 /*-----------------------------------------------------------------*/
11165 /* genGenPointerGet - gget value from generic pointer space        */
11166 /*-----------------------------------------------------------------*/
11167 static void genGenPointerGet (operand *left,
11168                               operand *result, iCode *ic)
11169 {
11170   int size, offset, lit;
11171   sym_link *retype = getSpec(operandType(result));
11172   char fgptrget[32];
11173
11174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11175     pic16_aopOp(left,ic,FALSE);
11176     pic16_aopOp(result,ic,TRUE);
11177     size = AOP_SIZE(result);
11178
11179     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11180
11181     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11182
11183       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11184       // load FSR0 from immediate
11185       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11186
11187       werror(W_POSSBUG2, __FILE__, __LINE__);
11188
11189       offset = 0;
11190       while(size--) {
11191         if(size) {
11192           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11193         } else {
11194           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11195         }
11196         offset++;
11197       }
11198
11199       goto release;
11200
11201     } else { /* we need to get it byte by byte */
11202
11203       /* set up WREG:PRODL:FSR0L with address from left */
11204       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11205       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11206       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11207       
11208       switch( size ) {
11209         case 1: strcpy(fgptrget, "__gptrget1"); break;
11210         case 2: strcpy(fgptrget, "__gptrget2"); break;
11211         case 3: strcpy(fgptrget, "__gptrget3"); break;
11212         case 4: strcpy(fgptrget, "__gptrget4"); break;
11213         default:
11214           werror(W_POSSBUG2, __FILE__, __LINE__);
11215           abort();
11216       }
11217       
11218       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11219       
11220       assignResultValue(result, 1);
11221       
11222       {
11223         symbol *sym;
11224
11225           sym = newSymbol( fgptrget, 0 );
11226           sym->used++;
11227           strcpy(sym->rname, fgptrget);
11228           checkAddSym(&externs, sym);
11229
11230 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11231       }
11232               
11233       goto release;
11234     }
11235
11236   /* if bit then unpack */
11237     if (IS_BITFIELD(retype)) 
11238       genUnpackBits(result,left,"BAD",GPOINTER);
11239
11240 release:
11241   pic16_freeAsmop(left,NULL,ic,TRUE);
11242   pic16_freeAsmop(result,NULL,ic,TRUE);
11243 }
11244
11245 /*-----------------------------------------------------------------*/
11246 /* genConstPointerGet - get value from const generic pointer space */
11247 /*-----------------------------------------------------------------*/
11248 static void genConstPointerGet (operand *left,
11249                                 operand *result, iCode *ic)
11250 {
11251   //sym_link *retype = getSpec(operandType(result));
11252   // symbol *albl = newiTempLabel(NULL);        // patch 15
11253   // symbol *blbl = newiTempLabel(NULL);        //
11254   // PIC_OPCODE poc;                            // patch 15
11255   int size;
11256   int offset = 0;
11257
11258   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11259   pic16_aopOp(left,ic,FALSE);
11260   pic16_aopOp(result,ic,TRUE);
11261   size = AOP_SIZE(result);
11262
11263   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11264
11265   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11266
11267   // set up table pointer
11268   if( (AOP_TYPE(left) == AOP_PCODE) 
11269       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11270           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11271     {
11272       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11273       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11274       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11275       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11276       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11277       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11278   } else {
11279     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11280     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11281     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11282   }
11283
11284   while(size--) {
11285     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11286     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11287     offset++;
11288   }
11289     
11290   pic16_freeAsmop(left,NULL,ic,TRUE);
11291   pic16_freeAsmop(result,NULL,ic,TRUE);
11292 }
11293
11294
11295 /*-----------------------------------------------------------------*/
11296 /* genPointerGet - generate code for pointer get                   */
11297 /*-----------------------------------------------------------------*/
11298 static void genPointerGet (iCode *ic)
11299 {
11300   operand *left, *result ;
11301   sym_link *type, *etype;
11302   int p_type;
11303
11304     FENTRY;
11305     
11306     left = IC_LEFT(ic);
11307     result = IC_RESULT(ic) ;
11308
11309     /* depending on the type of pointer we need to
11310     move it to the correct pointer register */
11311     type = operandType(left);
11312     etype = getSpec(type);
11313
11314 #if 0
11315     if (IS_PTR_CONST(type))
11316 #else
11317     if (IS_CODEPTR(type))
11318 #endif
11319       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11320
11321     /* if left is of type of pointer then it is simple */
11322     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11323       p_type = DCL_TYPE(type);
11324     else {
11325       /* we have to go by the storage class */
11326       p_type = PTR_TYPE(SPEC_OCLS(etype));
11327
11328       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11329
11330       if (SPEC_OCLS(etype)->codesp ) {
11331         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11332         //p_type = CPOINTER ;   
11333       } else
11334       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11335         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11336         /*p_type = FPOINTER ;*/ 
11337       } else
11338       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11339         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11340         /* p_type = PPOINTER; */
11341       } else
11342       if (SPEC_OCLS(etype) == idata ) {
11343         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11344         /* p_type = IPOINTER; */
11345       } else {
11346         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11347         /* p_type = POINTER ; */
11348       }
11349     }
11350
11351     /* now that we have the pointer type we assign
11352     the pointer values */
11353     switch (p_type) {
11354       case POINTER:     
11355       case IPOINTER:
11356         genNearPointerGet (left,result,ic);
11357         break;
11358
11359       case PPOINTER:
11360         genPagedPointerGet(left,result,ic);
11361         break;
11362
11363       case FPOINTER:
11364         genFarPointerGet (left,result,ic);
11365         break;
11366
11367       case CPOINTER:
11368         genConstPointerGet (left,result,ic);
11369         //pic16_emitcodePointerGet (left,result,ic);
11370         break;
11371
11372       case GPOINTER:
11373 #if 0
11374       if (IS_PTR_CONST(type))
11375         genConstPointerGet (left,result,ic);
11376       else
11377 #endif
11378         genGenPointerGet (left,result,ic);
11379       break;
11380
11381     default:
11382       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11383               "genPointerGet: illegal pointer type");
11384     
11385     }
11386 }
11387
11388 /*-----------------------------------------------------------------*/
11389 /* genPackBits - generates code for packed bit storage             */
11390 /*-----------------------------------------------------------------*/
11391 static void genPackBits (sym_link    *etype , operand *result,
11392                          operand *right ,
11393                          char *rname, int p_type)
11394 {
11395   int shCnt = 0 ;
11396   int offset = 0  ;
11397   int rLen = 0 ;
11398   int blen, bstr ;   
11399   sym_link *retype;
11400
11401         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11402         blen = SPEC_BLEN(etype);
11403         bstr = SPEC_BSTR(etype);
11404
11405         retype = getSpec(operandType(right));
11406
11407         if(AOP_TYPE(right) == AOP_LIT) {
11408                 if((blen == 1) && (bstr < 8)) {
11409                   unsigned long lit;
11410                         /* it is a single bit, so use the appropriate bit instructions */
11411
11412                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11413
11414                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11415 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11416                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11417                                 /* workaround to reduce the extra lfsr instruction */
11418                                 if(lit) {
11419                                         pic16_emitpcode(POC_BSF,
11420                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11421                                 } else {
11422                                         pic16_emitpcode(POC_BCF,
11423                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11424                                 }
11425                         } else {
11426                                 pic16_loadFSR0(result, 0);
11427                                 if(lit) {
11428                                         pic16_emitpcode(POC_BSF,
11429                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11430                                 } else {
11431                                         pic16_emitpcode(POC_BCF,
11432                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11433                                 }
11434                         }
11435         
11436                   return;
11437                 }
11438                 /* move literal to W */
11439                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11440                 offset++;
11441         } else
11442         if(IS_BITFIELD(retype) 
11443           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11444           && (blen == 1)) {
11445           int rblen, rbstr;
11446
11447             rblen = SPEC_BLEN( retype );
11448             rbstr = SPEC_BSTR( retype );
11449             
11450
11451             if(IS_BITFIELD(etype)) {
11452               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11453               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11454             } else {
11455               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11456             }
11457             
11458             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11459             
11460             if(IS_BITFIELD(etype)) {
11461               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11462             } else {
11463               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11464             }
11465
11466             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11467             
11468             return;
11469         } else {
11470           /* move right to W */
11471           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11472         }
11473
11474         /* if the bit length is less than or   */
11475         /* it exactly fits a byte then         */
11476         if((shCnt=SPEC_BSTR(etype))
11477                 || SPEC_BLEN(etype) <= 8 )  {
11478                 int fsr0_setup = 0;
11479
11480                 if (blen != 8 || bstr != 0) {
11481                   // we need to combine the value with the old value
11482                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11483
11484           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11485                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11486                 
11487                   /* shift left acc */
11488                   AccLsh(shCnt);
11489
11490                   /* using PRODH as a temporary register here */
11491                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11492
11493                  if (OP_SYMBOL(result)->remat) {
11494                    // access symbol directly
11495                    pic16_mov2w (AOP(result), 0);
11496                  } else {
11497                   /* get old value */
11498                   switch (p_type) {
11499                         case FPOINTER:
11500                         case POINTER:
11501                                 pic16_loadFSR0( result, 0 );
11502                                 fsr0_setup = 1;
11503                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11504 //                              pic16_emitcode ("mov","b,a");
11505 //                              pic16_emitcode("mov","a,@%s",rname);
11506                                 break;
11507
11508                         case GPOINTER:
11509                                 if (AOP(result)->aopu.aop_reg[2]) {
11510                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11511                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11512                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11513                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11514                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11515                                   {
11516                                     symbol *sym;
11517                                     sym = newSymbol( "__gptrget1", 0 );
11518                                     strcpy(sym->rname, "__gptrget1");
11519                                     checkAddSym(&externs, sym);
11520                                   }
11521                                 } else {
11522                                   // data pointer (just 2 byte given)
11523                                   pic16_loadFSR0( result, 0 );
11524                                   fsr0_setup = 1;
11525                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11526                                 }
11527                                 
11528                                 // warnings will be emitted below
11529                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11530                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11531                                 break;
11532
11533                         default:
11534                                 assert (0 && "invalid pointer type specified");
11535                                 break;
11536                   }
11537                  }
11538 #if 1
11539                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11540                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11541                                         (unsigned char)(0xff >> (8-bstr))) ));
11542                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11543                 } // if (blen != 8 || bstr != 0)
11544
11545                 /* write new value back */
11546                if (OP_SYMBOL(result)->remat) {
11547                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11548                } else {
11549                 switch (p_type) {
11550                         case FPOINTER:
11551                         case POINTER:
11552                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11553                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11554                                 break;
11555
11556                         case GPOINTER:
11557                                 if (AOP(result)->aopu.aop_reg[2]) {
11558                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11559                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11560                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11561                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11562                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11563                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11564                                   {
11565                                     symbol *sym;
11566                                     sym = newSymbol( "__gptrput1", 0 );
11567                                     strcpy(sym->rname, "__gptrput1");
11568                                     checkAddSym(&externs, sym);
11569                                   }
11570                                 } else {
11571                                   // data pointer (just 2 byte given)
11572                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11573                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11574                                 }
11575                                 
11576                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11577                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11578                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11579                                 break;
11580
11581                         default:
11582                                 assert (0 && "invalid pointer type specified");
11583                                 break;
11584                 }
11585                }
11586 #endif
11587
11588           return;
11589         }
11590
11591
11592 #if 0
11593         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11594         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11595         exit(-1);
11596 #endif
11597
11598
11599     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11600     rLen = SPEC_BLEN(etype)-8;
11601     
11602     /* now generate for lengths greater than one byte */
11603     while (1) {
11604         rLen -= 8 ;
11605         if (rLen <= 0 ) {
11606           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11607           break ;
11608         }
11609
11610         switch (p_type) {
11611             case POINTER:
11612                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11613                 break;
11614
11615 /*
11616             case FPOINTER:
11617                 MOVA(l);
11618                 pic16_emitcode("movx","@dptr,a");
11619                 break;
11620
11621             case GPOINTER:
11622                 MOVA(l);
11623                 DEBUGpic16_emitcode(";lcall","__gptrput");
11624                 break;  
11625 */
11626           default:
11627             assert(0);
11628         }   
11629
11630
11631         pic16_mov2w(AOP(right), offset++);
11632     }
11633
11634     /* last last was not complete */
11635     if (rLen)   {
11636         /* save the byte & read byte */
11637         switch (p_type) {
11638             case POINTER:
11639 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11640                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11641                 break;
11642
11643 /*
11644             case FPOINTER:
11645                 pic16_emitcode ("mov","b,a");
11646                 pic16_emitcode("movx","a,@dptr");
11647                 break;
11648
11649             case GPOINTER:
11650                 pic16_emitcode ("push","b");
11651                 pic16_emitcode ("push","acc");
11652                 pic16_emitcode ("lcall","__gptrget");
11653                 pic16_emitcode ("pop","b");
11654                 break;
11655 */
11656             default:
11657               assert(0);
11658         }
11659         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11660         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11661         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11662 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11663 //        pic16_emitcode ("orl","a,b");
11664     }
11665
11666 //    if (p_type == GPOINTER)
11667 //        pic16_emitcode("pop","b");
11668
11669     switch (p_type) {
11670
11671       case POINTER:
11672         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11673 //      pic16_emitcode("mov","@%s,a",rname);
11674         break;
11675 /*
11676       case FPOINTER:
11677         pic16_emitcode("movx","@dptr,a");
11678         break;
11679         
11680       case GPOINTER:
11681         DEBUGpic16_emitcode(";lcall","__gptrput");
11682         break;                  
11683 */
11684       default:
11685         assert(0);
11686     }
11687     
11688 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11689 }
11690 /*-----------------------------------------------------------------*/
11691 /* genDataPointerSet - remat pointer to data space                 */
11692 /*-----------------------------------------------------------------*/
11693 static void genDataPointerSet(operand *right,
11694                               operand *result,
11695                               iCode *ic)
11696 {
11697     int size, offset = 0, resoffset=0 ;
11698
11699     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11700     pic16_aopOp(right,ic,FALSE);
11701
11702     size = AOP_SIZE(right);
11703
11704 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11705
11706 #if 0
11707     if ( AOP_TYPE(result) == AOP_PCODE) {
11708       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11709               AOP(result)->aopu.pcop->name,
11710                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11711               PCOR(AOP(result)->aopu.pcop)->instance:
11712               PCOI(AOP(result)->aopu.pcop)->offset);
11713     }
11714 #endif
11715
11716         if(AOP(result)->aopu.pcop->type == PO_DIR)
11717                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11718
11719         while (size--) {
11720                 if (AOP_TYPE(right) == AOP_LIT) {
11721                   unsigned int lit;
11722
11723                     if(!IS_FLOAT(operandType( right )))
11724                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11725                     else {
11726                       union {
11727                         unsigned long lit_int;
11728                         float lit_float;
11729                       } info;
11730         
11731                         /* take care if literal is a float */
11732                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11733                         lit = info.lit_int;
11734                     }
11735
11736                     lit = lit >> (8*offset);
11737                     if(lit&0xff) {
11738                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11739                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11740                     } else {
11741                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11742                     }
11743                 } else {
11744                   pic16_mov2w(AOP(right), offset);
11745                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11746                 }
11747                 offset++;
11748                 resoffset++;
11749         }
11750
11751     pic16_freeAsmop(right,NULL,ic,TRUE);
11752 }
11753
11754
11755
11756 /*-----------------------------------------------------------------*/
11757 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11758 /*-----------------------------------------------------------------*/
11759 static void genNearPointerSet (operand *right,
11760                                operand *result, 
11761                                iCode *ic)
11762 {
11763   asmop *aop = NULL;
11764   sym_link *retype;
11765   sym_link *ptype = operandType(result);
11766   sym_link *resetype;
11767     
11768         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11769         retype= getSpec(operandType(right));
11770         resetype = getSpec(operandType(result));
11771   
11772         pic16_aopOp(result,ic,FALSE);
11773     
11774         /* if the result is rematerializable &
11775          * in data space & not a bit variable */
11776         
11777         /* and result is not a bit variable */
11778         if (AOP_TYPE(result) == AOP_PCODE
11779 //              && AOP_TYPE(result) == AOP_IMMD
11780                 && DCL_TYPE(ptype) == POINTER
11781                 && !IS_BITFIELD(retype)
11782                 && !IS_BITFIELD(resetype)) {
11783
11784                 genDataPointerSet (right,result,ic);
11785                 pic16_freeAsmop(result,NULL,ic,TRUE);
11786           return;
11787         }
11788
11789         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11790         pic16_aopOp(right,ic,FALSE);
11791         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11792
11793         /* if the value is already in a pointer register
11794          * then don't need anything more */
11795         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11796           /* otherwise get a free pointer register */
11797           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11798
11799           ;
11800         }
11801
11802         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11803
11804         /* if bitfield then unpack the bits */
11805         if (IS_BITFIELD(resetype)) {
11806                 genPackBits (resetype, result, right, NULL, POINTER);
11807         } else {
11808                 /* we have can just get the values */
11809           int size = AOP_SIZE(right);
11810           int offset = 0 ;    
11811
11812             pic16_loadFSR0(result, 0);
11813             
11814                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11815                 while (size--) {
11816                                 if (AOP_TYPE(right) == AOP_LIT) {
11817                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11818                                         if (size) {
11819                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11820                                         } else {
11821                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11822                                         }
11823                                 } else { // no literal
11824                                         if(size) {
11825                                                 pic16_emitpcode(POC_MOVFF,
11826                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11827                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11828                                         } else {
11829                                                 pic16_emitpcode(POC_MOVFF,
11830                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11831                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11832                                         }
11833                                 }
11834                         offset++;
11835                 }
11836         }
11837
11838         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11839         /* now some housekeeping stuff */
11840         if (aop) {
11841           /* we had to allocate for this iCode */
11842           pic16_freeAsmop(NULL,aop,ic,TRUE);
11843         } else { 
11844           /* we did not allocate which means left
11845            * already in a pointer register, then
11846            * if size > 0 && this could be used again
11847            * we have to point it back to where it 
11848            * belongs */
11849           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11850           if (AOP_SIZE(right) > 1
11851             && !OP_SYMBOL(result)->remat
11852             && ( OP_SYMBOL(result)->liveTo > ic->seq
11853             || ic->depth )) {
11854
11855               int size = AOP_SIZE(right) - 1;
11856
11857                 while (size--)
11858                   pic16_emitcode("decf","fsr0,f");
11859                   //pic16_emitcode("dec","%s",rname);
11860             }
11861         }
11862
11863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11864     /* done */
11865 //release:
11866     pic16_freeAsmop(right,NULL,ic,TRUE);
11867     pic16_freeAsmop(result,NULL,ic,TRUE);
11868 }
11869
11870 /*-----------------------------------------------------------------*/
11871 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11872 /*-----------------------------------------------------------------*/
11873 static void genPagedPointerSet (operand *right,
11874                                operand *result, 
11875                                iCode *ic)
11876 {
11877     asmop *aop = NULL;
11878     regs *preg = NULL ;
11879     char *rname , *l;
11880     sym_link *retype;
11881        
11882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11883
11884     retype= getSpec(operandType(right));
11885     
11886     pic16_aopOp(result,ic,FALSE);
11887     
11888     /* if the value is already in a pointer register
11889        then don't need anything more */
11890     if (!AOP_INPREG(AOP(result))) {
11891         /* otherwise get a free pointer register */
11892         aop = newAsmop(0);
11893         preg = getFreePtr(ic,&aop,FALSE);
11894         pic16_emitcode("mov","%s,%s",
11895                 preg->name,
11896                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11897         rname = preg->name ;
11898     } else
11899         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11900     
11901     pic16_freeAsmop(result,NULL,ic,TRUE);
11902     pic16_aopOp (right,ic,FALSE);
11903
11904     /* if bitfield then unpack the bits */
11905     if (IS_BITFIELD(retype)) 
11906         genPackBits (retype,result,right,rname,PPOINTER);
11907     else {
11908         /* we have can just get the values */
11909         int size = AOP_SIZE(right);
11910         int offset = 0 ;        
11911         
11912         while (size--) {
11913             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11914             
11915             MOVA(l);
11916             pic16_emitcode("movx","@%s,a",rname);
11917
11918             if (size)
11919                 pic16_emitcode("inc","%s",rname);
11920
11921             offset++;
11922         }
11923     }
11924     
11925     /* now some housekeeping stuff */
11926     if (aop) {
11927         /* we had to allocate for this iCode */
11928         pic16_freeAsmop(NULL,aop,ic,TRUE);
11929     } else { 
11930         /* we did not allocate which means left
11931            already in a pointer register, then
11932            if size > 0 && this could be used again
11933            we have to point it back to where it 
11934            belongs */
11935         if (AOP_SIZE(right) > 1 &&
11936             !OP_SYMBOL(result)->remat &&
11937             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11938               ic->depth )) {
11939             int size = AOP_SIZE(right) - 1;
11940             while (size--)
11941                 pic16_emitcode("dec","%s",rname);
11942         }
11943     }
11944
11945     /* done */
11946     pic16_freeAsmop(right,NULL,ic,TRUE);
11947     
11948         
11949 }
11950
11951 /*-----------------------------------------------------------------*/
11952 /* genFarPointerSet - set value from far space                     */
11953 /*-----------------------------------------------------------------*/
11954 static void genFarPointerSet (operand *right,
11955                               operand *result, iCode *ic)
11956 {
11957     int size, offset ;
11958     sym_link *retype = getSpec(operandType(right));
11959
11960     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11961     pic16_aopOp(result,ic,FALSE);
11962
11963     /* if the operand is already in dptr 
11964     then we do nothing else we move the value to dptr */
11965     if (AOP_TYPE(result) != AOP_STR) {
11966         /* if this is remateriazable */
11967         if (AOP_TYPE(result) == AOP_IMMD)
11968             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11969         else { /* we need to get it byte by byte */
11970             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11971             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11972             if (options.model == MODEL_FLAT24)
11973             {
11974                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11975             }
11976         }
11977     }
11978     /* so dptr know contains the address */
11979     pic16_freeAsmop(result,NULL,ic,TRUE);
11980     pic16_aopOp(right,ic,FALSE);
11981
11982     /* if bit then unpack */
11983     if (IS_BITFIELD(retype)) 
11984         genPackBits(retype,result,right,"dptr",FPOINTER);
11985     else {
11986         size = AOP_SIZE(right);
11987         offset = 0 ;
11988
11989         while (size--) {
11990             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11991             MOVA(l);
11992             pic16_emitcode("movx","@dptr,a");
11993             if (size)
11994                 pic16_emitcode("inc","dptr");
11995         }
11996     }
11997
11998     pic16_freeAsmop(right,NULL,ic,TRUE);
11999 }
12000
12001 /*-----------------------------------------------------------------*/
12002 /* genGenPointerSet - set value from generic pointer space         */
12003 /*-----------------------------------------------------------------*/
12004 #if 0
12005 static void genGenPointerSet (operand *right,
12006                               operand *result, iCode *ic)
12007 {
12008         int i, size, offset, lit;
12009         sym_link *retype = getSpec(operandType(right));
12010
12011         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12012
12013         pic16_aopOp(result,ic,FALSE);
12014         pic16_aopOp(right,ic,FALSE);
12015         size = AOP_SIZE(right);
12016         offset = 0;
12017
12018         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12019
12020         /* if the operand is already in dptr 
12021                 then we do nothing else we move the value to dptr */
12022         if (AOP_TYPE(result) != AOP_STR) {
12023                 /* if this is remateriazable */
12024                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12025                 // WARNING: anythig until "else" is untested!
12026                 if (AOP_TYPE(result) == AOP_IMMD) {
12027                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12028                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12029                         // load FSR0 from immediate
12030                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12031                         offset = 0;
12032                         while(size--) {
12033                                 if(size) {
12034                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12035                                 } else {
12036                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12037                                 }
12038                                 offset++;
12039                         }
12040                         goto release;
12041                 }
12042                 else { /* we need to get it byte by byte */
12043                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12044                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12045
12046                         // set up FSR0 with address of result
12047                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12048                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12049
12050                         /* hack hack! see if this the FSR. If so don't load W */
12051                         if(AOP_TYPE(right) != AOP_ACC) {
12052
12053                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12054
12055                                 if(AOP_TYPE(right) == AOP_LIT)
12056                                 {
12057                                         // copy literal
12058                                         // note: pic16_popGet handles sign extension
12059                                         for(i=0;i<size;i++) {
12060                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12061                                                 if(i < size-1)
12062                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12063                                                 else
12064                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12065                                         }
12066                                 } else {
12067                                         // copy regs
12068
12069                                         for(i=0;i<size;i++) {
12070                                                 if(i < size-1)
12071                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12072                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12073                                                 else
12074                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12075                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12076                                         }
12077                                 }
12078                                 goto release;
12079                         } 
12080                         // right = ACC
12081                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12082                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12083                         goto release;
12084         } // if (AOP_TYPE(result) != AOP_IMMD)
12085
12086         } // if (AOP_TYPE(result) != AOP_STR)
12087         /* so dptr know contains the address */
12088
12089
12090         /* if bit then unpack */
12091         if (IS_BITFIELD(retype)) 
12092                 genPackBits(retype,result,right,"dptr",GPOINTER);
12093         else {
12094                 size = AOP_SIZE(right);
12095                 offset = 0 ;
12096
12097                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12098
12099                 // set up FSR0 with address of result
12100                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12101                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12102         
12103                 while (size--) {
12104                         if (AOP_TYPE(right) == AOP_LIT) {
12105                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12106                                 if (size) {
12107                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12108                                 } else {
12109                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12110                                 }
12111                         } else { // no literal
12112                                 if(size) {
12113                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12114                                 } else {
12115                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12116                                 }
12117                         }
12118                         offset++;
12119                 }
12120         }
12121
12122         release:
12123         pic16_freeAsmop(right,NULL,ic,TRUE);
12124         pic16_freeAsmop(result,NULL,ic,TRUE);
12125 }
12126 #endif
12127
12128 static void genGenPointerSet (operand *right,
12129                               operand *result, iCode *ic)
12130 {
12131   int size;
12132   sym_link *retype = getSpec(operandType(right));
12133   char fgptrput[32];
12134
12135     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12136
12137     pic16_aopOp(result,ic,FALSE);
12138     pic16_aopOp(right,ic,FALSE);
12139     size = AOP_SIZE(right);
12140
12141     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12142
12143
12144     /* if bit then unpack */
12145     if (IS_BITFIELD(retype)) {
12146 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12147       genPackBits(retype,result,right,"dptr",GPOINTER);
12148       goto release;
12149     }
12150
12151     size = AOP_SIZE(right);
12152
12153     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12154
12155
12156
12157     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12158
12159     /* value of right+0 is placed on stack, which will be retrieved
12160      * by the support function this restoring the stack. The important
12161      * thing is that there is no need to manually restore stack pointer
12162      * here */
12163     pushaop(AOP(right), 0);
12164 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12165     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12166     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12167     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12168     
12169     /* load address to write to in WREG:FSR0H:FSR0L */
12170     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12171                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12172     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12173                                 pic16_popCopyReg(&pic16_pc_prodl)));
12174     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12175     
12176
12177     /* put code here */
12178     switch (size) {
12179       case 1: strcpy(fgptrput, "__gptrput1"); break;
12180       case 2: strcpy(fgptrput, "__gptrput2"); break;
12181       case 3: strcpy(fgptrput, "__gptrput3"); break;
12182       case 4: strcpy(fgptrput, "__gptrput4"); break;
12183       default:
12184         werror(W_POSSBUG2, __FILE__, __LINE__);
12185         abort();
12186     }
12187     
12188     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12189     
12190     {
12191       symbol *sym;
12192                   
12193         sym = newSymbol( fgptrput, 0 );
12194         sym->used++;
12195         strcpy(sym->rname, fgptrput);
12196         checkAddSym(&externs, sym);
12197     }
12198
12199 release:
12200     pic16_freeAsmop(right,NULL,ic,TRUE);
12201     pic16_freeAsmop(result,NULL,ic,TRUE);
12202 }
12203
12204 /*-----------------------------------------------------------------*/
12205 /* genPointerSet - stores the value into a pointer location        */
12206 /*-----------------------------------------------------------------*/
12207 static void genPointerSet (iCode *ic)
12208 {    
12209   operand *right, *result ;
12210   sym_link *type, *etype;
12211   int p_type;
12212
12213     FENTRY;
12214
12215     right = IC_RIGHT(ic);
12216     result = IC_RESULT(ic) ;
12217
12218     /* depending on the type of pointer we need to
12219     move it to the correct pointer register */
12220     type = operandType(result);
12221     etype = getSpec(type);
12222     /* if left is of type of pointer then it is simple */
12223     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12224         p_type = DCL_TYPE(type);
12225     }
12226     else {
12227         /* we have to go by the storage class */
12228         p_type = PTR_TYPE(SPEC_OCLS(etype));
12229
12230 /*      if (SPEC_OCLS(etype)->codesp ) { */
12231 /*          p_type = CPOINTER ;  */
12232 /*      } */
12233 /*      else */
12234 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12235 /*              p_type = FPOINTER ; */
12236 /*          else */
12237 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12238 /*                  p_type = PPOINTER ; */
12239 /*              else */
12240 /*                  if (SPEC_OCLS(etype) == idata ) */
12241 /*                      p_type = IPOINTER ; */
12242 /*                  else */
12243 /*                      p_type = POINTER ; */
12244     }
12245
12246     /* now that we have the pointer type we assign
12247     the pointer values */
12248     switch (p_type) {
12249       case POINTER:
12250       case IPOINTER:
12251         genNearPointerSet (right,result,ic);
12252         break;
12253
12254       case PPOINTER:
12255         genPagedPointerSet (right,result,ic);
12256         break;
12257
12258       case FPOINTER:
12259         genFarPointerSet (right,result,ic);
12260         break;
12261         
12262       case GPOINTER:
12263         genGenPointerSet (right,result,ic);
12264         break;
12265
12266       default:
12267         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12268           "genPointerSet: illegal pointer type");
12269     }
12270 }
12271
12272 /*-----------------------------------------------------------------*/
12273 /* genIfx - generate code for Ifx statement                        */
12274 /*-----------------------------------------------------------------*/
12275 static void genIfx (iCode *ic, iCode *popIc)
12276 {
12277   operand *cond = IC_COND(ic);
12278   int isbit =0;
12279
12280     FENTRY;
12281
12282     pic16_aopOp(cond,ic,FALSE);
12283
12284     /* get the value into acc */
12285     if (AOP_TYPE(cond) != AOP_CRY)
12286       pic16_toBoolean(cond);
12287     else
12288       isbit = 1;
12289     /* the result is now in the accumulator */
12290     pic16_freeAsmop(cond,NULL,ic,TRUE);
12291
12292     /* if there was something to be popped then do it */
12293     if (popIc)
12294       genIpop(popIc);
12295
12296     /* if the condition is  a bit variable */
12297     if (isbit && IS_ITEMP(cond) && 
12298         SPIL_LOC(cond)) {
12299       genIfxJump(ic,"c");
12300       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12301     } else {
12302       if (isbit && !IS_ITEMP(cond))
12303         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12304         else
12305         genIfxJump(ic,"a");
12306     }
12307     ic->generated = 1;
12308 }
12309
12310 /*-----------------------------------------------------------------*/
12311 /* genAddrOf - generates code for address of                       */
12312 /*-----------------------------------------------------------------*/
12313 static void genAddrOf (iCode *ic)
12314 {
12315   operand *result, *left;
12316   int size;
12317   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12318   pCodeOp *pcop0, *pcop1, *pcop2;
12319
12320     FENTRY;
12321
12322     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12323
12324     sym = OP_SYMBOL( IC_LEFT(ic) );
12325     
12326     if(sym->onStack) {
12327       /* get address of symbol on stack */
12328       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12329 #if 0
12330       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12331                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12332 #endif
12333
12334       // operands on stack are accessible via "FSR2 + index" with index
12335       // starting at 2 for arguments and growing from 0 downwards for
12336       // local variables (index == 0 is not assigned so we add one here)
12337       {
12338         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12339         if (soffs <= 0) {
12340           assert (soffs < 0);
12341           soffs++;
12342         } // if
12343         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12344         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12345         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12346         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12347         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12348         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12349         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12350       }
12351
12352       goto release;
12353     }
12354         
12355 //      if(pic16_debug_verbose) {
12356 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12357 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12358 //      }
12359         
12360     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12361     size = AOP_SIZE(IC_RESULT(ic));
12362
12363     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12364     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12365     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12366         
12367     if (size == 3) {
12368       pic16_emitpcode(POC_MOVLW, pcop0);
12369       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12370       pic16_emitpcode(POC_MOVLW, pcop1);
12371       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12372       pic16_emitpcode(POC_MOVLW, pcop2);
12373       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12374     } else
12375     if (size == 2) {
12376       pic16_emitpcode(POC_MOVLW, pcop0);
12377       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12378       pic16_emitpcode(POC_MOVLW, pcop1);
12379     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12380     } else {
12381       pic16_emitpcode(POC_MOVLW, pcop0);
12382       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12383     }
12384
12385     pic16_freeAsmop(left, NULL, ic, FALSE);
12386 release:
12387     pic16_freeAsmop(result,NULL,ic,TRUE);
12388 }
12389
12390
12391 #if 0
12392 /*-----------------------------------------------------------------*/
12393 /* genFarFarAssign - assignment when both are in far space         */
12394 /*-----------------------------------------------------------------*/
12395 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12396 {
12397     int size = AOP_SIZE(right);
12398     int offset = 0;
12399     char *l ;
12400     /* first push the right side on to the stack */
12401     while (size--) {
12402         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12403         MOVA(l);
12404         pic16_emitcode ("push","acc");
12405     }
12406     
12407     pic16_freeAsmop(right,NULL,ic,FALSE);
12408     /* now assign DPTR to result */
12409     pic16_aopOp(result,ic,FALSE);
12410     size = AOP_SIZE(result);
12411     while (size--) {
12412         pic16_emitcode ("pop","acc");
12413         pic16_aopPut(AOP(result),"a",--offset);
12414     }
12415     pic16_freeAsmop(result,NULL,ic,FALSE);
12416         
12417 }
12418 #endif
12419
12420 /*-----------------------------------------------------------------*/
12421 /* genAssign - generate code for assignment                        */
12422 /*-----------------------------------------------------------------*/
12423 static void genAssign (iCode *ic)
12424 {
12425   operand *result, *right;
12426   int size, offset,know_W;
12427   unsigned long lit = 0L;
12428
12429   result = IC_RESULT(ic);
12430   right  = IC_RIGHT(ic) ;
12431
12432   FENTRY;
12433   
12434   /* if they are the same */
12435   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12436     return ;
12437
12438   /* reversed order operands are aopOp'ed so that result operand
12439    * is effective in case right is a stack symbol. This maneauver
12440    * allows to use the _G.resDirect flag later */
12441   pic16_aopOp(result,ic,TRUE);
12442   pic16_aopOp(right,ic,FALSE);
12443
12444   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12445
12446   /* if they are the same registers */
12447   if (pic16_sameRegs(AOP(right),AOP(result)))
12448     goto release;
12449
12450   /* if the result is a bit */
12451   if (AOP_TYPE(result) == AOP_CRY) {
12452     /* if the right size is a literal then
12453        we know what the value is */
12454     if (AOP_TYPE(right) == AOP_LIT) {
12455           
12456       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12457                   pic16_popGet(AOP(result),0));
12458
12459       if (((int) operandLitValue(right))) 
12460         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12461                        AOP(result)->aopu.aop_dir,
12462                        AOP(result)->aopu.aop_dir);
12463       else
12464         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12465                        AOP(result)->aopu.aop_dir,
12466                        AOP(result)->aopu.aop_dir);
12467       goto release;
12468     }
12469
12470     /* the right is also a bit variable */
12471     if (AOP_TYPE(right) == AOP_CRY) {
12472       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12473       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12474       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12475
12476       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12477                      AOP(result)->aopu.aop_dir,
12478                      AOP(result)->aopu.aop_dir);
12479       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12480                      AOP(right)->aopu.aop_dir,
12481                      AOP(right)->aopu.aop_dir);
12482       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12483                      AOP(result)->aopu.aop_dir,
12484                      AOP(result)->aopu.aop_dir);
12485       goto release ;
12486     }
12487
12488     /* we need to or */
12489     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12490     pic16_toBoolean(right);
12491     emitSKPZ;
12492     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12493     //pic16_aopPut(AOP(result),"a",0);
12494     goto release ;
12495   }
12496
12497   /* bit variables done */
12498   /* general case */
12499   size = AOP_SIZE(result);
12500   offset = 0 ;
12501
12502   if(AOP_TYPE(right) == AOP_LIT) {
12503         if(!IS_FLOAT(operandType( right )))
12504                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12505         else {
12506            union {
12507               unsigned long lit_int;
12508               float lit_float;
12509             } info;
12510         
12511                 /* take care if literal is a float */
12512                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12513                 lit = info.lit_int;
12514         }
12515   }
12516
12517 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12518 //                      sizeof(unsigned long int), sizeof(float));
12519
12520
12521   if (AOP_TYPE(right) == AOP_REG) {
12522     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12523     while (size--) {
12524       
12525       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12526     } // while
12527     goto release;
12528   }
12529
12530   if(AOP_TYPE(right) != AOP_LIT
12531         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12532         && !IS_FUNC(OP_SYM_TYPE(right))
12533         ) {
12534         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12535         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12536
12537         // set up table pointer
12538         if(is_LitOp(right)) {
12539 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12540                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12541                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12542                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12543                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12544                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12545                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12546         } else {
12547 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12548                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12549                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12550                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12551                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12552                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12553                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12554         }
12555
12556         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12557         while(size--) {
12558                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12559                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12560                         pic16_popGet(AOP(result),offset)));
12561                 offset++;
12562         }
12563
12564         size = getSize(OP_SYM_ETYPE(right));
12565         if(AOP_SIZE(result) > size) {
12566                 size = AOP_SIZE(result) - size;
12567                 while(size--) {
12568                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12569                         offset++;
12570                 }
12571         }
12572         goto release;
12573   }
12574
12575
12576
12577 #if 0
12578 /* VR - What is this?! */
12579   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12580     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12581     if(aopIdx(AOP(result),0) == 4) {
12582
12583       /* this is a workaround to save value of right into wreg too,
12584        * value of wreg is going to be used later */
12585       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12586       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12587       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12588       goto release;
12589     } else
12590 //      assert(0);
12591       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12592   }
12593 #endif
12594
12595   know_W=-1;
12596   while (size--) {
12597   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12598     if(AOP_TYPE(right) == AOP_LIT) {
12599       if(lit&0xff) {
12600         if(know_W != (lit&0xff))
12601           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12602         know_W = lit&0xff;
12603         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12604       } else
12605         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12606
12607       lit >>= 8;
12608
12609     } else if (AOP_TYPE(right) == AOP_CRY) {
12610       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12611       if(offset == 0) {
12612         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12613         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12614         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12615       }
12616     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12617         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12618         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12619     } else {
12620       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12621
12622       if(!_G.resDirect)         /* use this aopForSym feature */
12623         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12624     }
12625             
12626     offset++;
12627   }
12628   
12629  release:
12630   pic16_freeAsmop (right,NULL,ic,FALSE);
12631   pic16_freeAsmop (result,NULL,ic,TRUE);
12632 }   
12633
12634 /*-----------------------------------------------------------------*/
12635 /* genJumpTab - generates code for jump table                       */
12636 /*-----------------------------------------------------------------*/
12637 static void genJumpTab (iCode *ic)
12638 {
12639   symbol *jtab;
12640   char *l;
12641   pCodeOp *jt_offs;
12642   pCodeOp *jt_offs_hi;
12643   pCodeOp *jt_label;
12644
12645     FENTRY;
12646
12647     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12648     /* get the condition into accumulator */
12649     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12650     MOVA(l);
12651     /* multiply by three */
12652     pic16_emitcode("add","a,acc");
12653     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12654
12655     jtab = newiTempLabel(NULL);
12656     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12657     pic16_emitcode("jmp","@a+dptr");
12658     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12659
12660 #if 0
12661     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12662     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12663     emitSKPNC;
12664     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12665     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12666     pic16_emitpLabel(jtab->key);
12667
12668 #else
12669
12670     jt_offs = pic16_popGetTempReg(0);
12671     jt_offs_hi = pic16_popGetTempReg(1);
12672     jt_label = pic16_popGetLabel (jtab->key);
12673     //fprintf (stderr, "Creating jump table...\n");
12674
12675     // calculate offset into jump table (idx * sizeof (GOTO))
12676     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12677     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12678     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12679     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12680     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12681     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12682     pic16_emitpcode(POC_MOVWF , jt_offs);
12683
12684     // prepare PCLATx (set to first entry in jump table)
12685     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12686     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12687     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12688     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12689     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12690
12691     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12692     pic16_emitpcode(POC_ADDWF , jt_offs);
12693     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12694     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12695     emitSKPNC;
12696     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12697
12698     // release temporaries and prepare jump into table (new PCL --> WREG)
12699     pic16_emitpcode(POC_MOVFW , jt_offs);
12700     pic16_popReleaseTempReg (jt_offs_hi, 1);
12701     pic16_popReleaseTempReg (jt_offs, 0);
12702
12703     // jump into the table
12704     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12705
12706     pic16_emitpLabelFORCE(jtab->key);
12707 #endif
12708
12709     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12710 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12711
12712     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12713     /* now generate the jump labels */
12714     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12715          jtab = setNextItem(IC_JTLABELS(ic))) {
12716 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12717         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12718         
12719     }
12720     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12721
12722 }
12723
12724 /*-----------------------------------------------------------------*/
12725 /* genMixedOperation - gen code for operators between mixed types  */
12726 /*-----------------------------------------------------------------*/
12727 /*
12728   TSD - Written for the PIC port - but this unfortunately is buggy.
12729   This routine is good in that it is able to efficiently promote 
12730   types to different (larger) sizes. Unfortunately, the temporary
12731   variables that are optimized out by this routine are sometimes
12732   used in other places. So until I know how to really parse the 
12733   iCode tree, I'm going to not be using this routine :(.
12734 */
12735 static int genMixedOperation (iCode *ic)
12736 {
12737 #if 0
12738   operand *result = IC_RESULT(ic);
12739   sym_link *ctype = operandType(IC_LEFT(ic));
12740   operand *right = IC_RIGHT(ic);
12741   int ret = 0;
12742   int big,small;
12743   int offset;
12744
12745   iCode *nextic;
12746   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12747
12748   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12749
12750   nextic = ic->next;
12751   if(!nextic)
12752     return 0;
12753
12754   nextright = IC_RIGHT(nextic);
12755   nextleft  = IC_LEFT(nextic);
12756   nextresult = IC_RESULT(nextic);
12757
12758   pic16_aopOp(right,ic,FALSE);
12759   pic16_aopOp(result,ic,FALSE);
12760   pic16_aopOp(nextright,  nextic, FALSE);
12761   pic16_aopOp(nextleft,   nextic, FALSE);
12762   pic16_aopOp(nextresult, nextic, FALSE);
12763
12764   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12765
12766     operand *t = right;
12767     right = nextright;
12768     nextright = t; 
12769
12770     pic16_emitcode(";remove right +","");
12771
12772   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12773 /*
12774     operand *t = right;
12775     right = nextleft;
12776     nextleft = t; 
12777 */
12778     pic16_emitcode(";remove left +","");
12779   } else
12780     return 0;
12781
12782   big = AOP_SIZE(nextleft);
12783   small = AOP_SIZE(nextright);
12784
12785   switch(nextic->op) {
12786
12787   case '+':
12788     pic16_emitcode(";optimize a +","");
12789     /* if unsigned or not an integral type */
12790     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12791       pic16_emitcode(";add a bit to something","");
12792     } else {
12793
12794       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12795
12796       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12797         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12798         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12799       } else
12800         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12801
12802       offset = 0;
12803       while(--big) {
12804
12805         offset++;
12806
12807         if(--small) {
12808           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12809             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12810             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12811           }
12812
12813           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12814           emitSKPNC;
12815           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12816                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12817                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12818           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12819           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12820
12821         } else {
12822           pic16_emitcode("rlf","known_zero,w");
12823
12824           /*
12825             if right is signed
12826               btfsc  right,7
12827                addlw ff
12828           */
12829           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12830             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12831             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12832           } else {
12833             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12834           }
12835         }
12836       }
12837       ret = 1;
12838     }
12839   }
12840   ret = 1;
12841
12842 release:
12843   pic16_freeAsmop(right,NULL,ic,TRUE);
12844   pic16_freeAsmop(result,NULL,ic,TRUE);
12845   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12846   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12847   if(ret)
12848     nextic->generated = 1;
12849
12850   return ret;
12851 #else
12852   return 0;
12853 #endif
12854 }
12855 /*-----------------------------------------------------------------*/
12856 /* genCast - gen code for casting                                  */
12857 /*-----------------------------------------------------------------*/
12858 static void genCast (iCode *ic)
12859 {
12860   operand *result = IC_RESULT(ic);
12861   sym_link *ctype = operandType(IC_LEFT(ic));
12862   sym_link *rtype = operandType(IC_RIGHT(ic));
12863   sym_link *restype = operandType(IC_RESULT(ic));
12864   operand *right = IC_RIGHT(ic);
12865   int size, offset ;
12866
12867
12868     FENTRY;
12869
12870         /* if they are equivalent then do nothing */
12871 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12872 //              return ;
12873
12874         pic16_aopOp(result,ic,FALSE);
12875         pic16_aopOp(right,ic,FALSE) ;
12876
12877         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12878
12879
12880         /* if the result is a bit */
12881         if (AOP_TYPE(result) == AOP_CRY) {
12882         
12883                 /* if the right size is a literal then
12884                  * we know what the value is */
12885                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12886
12887                 if (AOP_TYPE(right) == AOP_LIT) {
12888                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12889                                 pic16_popGet(AOP(result),0));
12890
12891                         if (((int) operandLitValue(right))) 
12892                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12893                                         AOP(result)->aopu.aop_dir,
12894                                         AOP(result)->aopu.aop_dir);
12895                         else
12896                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12897                                         AOP(result)->aopu.aop_dir,
12898                                         AOP(result)->aopu.aop_dir);
12899                         goto release;
12900                 }
12901
12902                 /* the right is also a bit variable */
12903                 if (AOP_TYPE(right) == AOP_CRY) {
12904                         emitCLRC;
12905                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12906
12907                         pic16_emitcode("clrc","");
12908                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12909                                 AOP(right)->aopu.aop_dir,
12910                                 AOP(right)->aopu.aop_dir);
12911                         pic16_aopPut(AOP(result),"c",0);
12912                         goto release ;
12913                 }
12914
12915                 /* we need to or */
12916                 if (AOP_TYPE(right) == AOP_REG) {
12917                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12918                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12919                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12920                 }
12921                 pic16_toBoolean(right);
12922                 pic16_aopPut(AOP(result),"a",0);
12923                 goto release ;
12924         }
12925
12926         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12927           int offset = 1;
12928
12929                 size = AOP_SIZE(result);
12930
12931                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12932
12933                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12934                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12935                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12936
12937                 while (size--)
12938                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12939
12940                 goto release;
12941         }
12942
12943         if(IS_BITFIELD(getSpec(restype))
12944           && IS_BITFIELD(getSpec(rtype))) {
12945           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12946         }
12947
12948         /* if they are the same size : or less */
12949         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12950
12951                 /* if they are in the same place */
12952                 if (pic16_sameRegs(AOP(right),AOP(result)))
12953                         goto release;
12954
12955                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12956 #if 0
12957                 if (IS_PTR_CONST(rtype))
12958 #else
12959                 if (IS_CODEPTR(rtype))
12960 #endif
12961                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12962
12963 #if 0
12964                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12965 #else
12966                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12967 #endif
12968                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12969
12970 #if 0
12971                 if(AOP_TYPE(right) == AOP_IMMD) {
12972                   pCodeOp *pcop0, *pcop1, *pcop2;
12973                   symbol *sym = OP_SYMBOL( right );
12974
12975                         size = AOP_SIZE(result);
12976                         /* low */
12977                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12978                         /* high */
12979                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12980                         /* upper */
12981                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12982         
12983                         if (size == 3) {
12984                                 pic16_emitpcode(POC_MOVLW, pcop0);
12985                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12986                                 pic16_emitpcode(POC_MOVLW, pcop1);
12987                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12988                                 pic16_emitpcode(POC_MOVLW, pcop2);
12989                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12990                         } else
12991                         if (size == 2) {
12992                                 pic16_emitpcode(POC_MOVLW, pcop0);
12993                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12994                                 pic16_emitpcode(POC_MOVLW, pcop1);
12995                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12996                         } else {
12997                                 pic16_emitpcode(POC_MOVLW, pcop0);
12998                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12999                         }
13000                 } else
13001 #endif
13002                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13003                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13004                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13005                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13006                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13007                         if(AOP_SIZE(result) <2)
13008                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13009                 } else {
13010                         /* if they in different places then copy */
13011                         size = AOP_SIZE(result);
13012                         offset = 0 ;
13013                         while (size--) {
13014                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13015                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13016                                 offset++;
13017                         }
13018                 }
13019                 goto release;
13020         }
13021
13022         /* if the result is of type pointer */
13023         if (IS_PTR(ctype)) {
13024           int p_type;
13025           sym_link *type = operandType(right);
13026           sym_link *etype = getSpec(type);
13027
13028                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13029
13030                 /* pointer to generic pointer */
13031                 if (IS_GENPTR(ctype)) {
13032                   char *l = zero;
13033             
13034                         if (IS_PTR(type)) 
13035                                 p_type = DCL_TYPE(type);
13036                         else {
13037                 /* we have to go by the storage class */
13038                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13039
13040 /*              if (SPEC_OCLS(etype)->codesp )  */
13041 /*                  p_type = CPOINTER ;  */
13042 /*              else */
13043 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13044 /*                      p_type = FPOINTER ; */
13045 /*                  else */
13046 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13047 /*                          p_type = PPOINTER; */
13048 /*                      else */
13049 /*                          if (SPEC_OCLS(etype) == idata ) */
13050 /*                              p_type = IPOINTER ; */
13051 /*                          else */
13052 /*                              p_type = POINTER ; */
13053             }
13054                 
13055             /* the first two bytes are known */
13056       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13057             size = GPTRSIZE - 1; 
13058             offset = 0 ;
13059             while (size--) {
13060               if(offset < AOP_SIZE(right)) {
13061                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13062                 mov2f(AOP(result), AOP(right), offset);
13063 /*
13064                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13065                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13066                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13067                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13068                 } else { 
13069                   
13070                   pic16_aopPut(AOP(result),
13071                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13072                          offset);
13073                 }
13074 */
13075               } else 
13076                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13077               offset++;
13078             }
13079             /* the last byte depending on type */
13080             switch (p_type) {
13081             case IPOINTER:
13082             case POINTER:
13083                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13084                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13085 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13086                 break;
13087
13088             case CPOINTER:
13089                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13090                 break;
13091
13092             case FPOINTER:
13093               pic16_emitcode(";BUG!? ","%d",__LINE__);
13094                 l = one;
13095                 break;
13096             case PPOINTER:
13097               pic16_emitcode(";BUG!? ","%d",__LINE__);
13098                 l = "#0x03";
13099                 break;
13100
13101             case GPOINTER:
13102                 if (GPTRSIZE > AOP_SIZE(right)) {
13103                   // assume data pointer... THIS MIGHT BE WRONG!
13104                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13105                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13106                 } else {
13107                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13108                 }
13109               break;
13110               
13111             default:
13112                 /* this should never happen */
13113                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13114                        "got unknown pointer type");
13115                 exit(1);
13116             }
13117             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13118             goto release ;
13119         }
13120         
13121         
13122         assert( 0 );
13123         /* just copy the pointers */
13124         size = AOP_SIZE(result);
13125         offset = 0 ;
13126         while (size--) {
13127             pic16_aopPut(AOP(result),
13128                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13129                    offset);
13130             offset++;
13131         }
13132         goto release ;
13133     }
13134     
13135
13136
13137     /* so we now know that the size of destination is greater
13138     than the size of the source.
13139     Now, if the next iCode is an operator then we might be
13140     able to optimize the operation without performing a cast.
13141     */
13142     if(genMixedOperation(ic))
13143       goto release;
13144
13145     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13146     
13147     /* we move to result for the size of source */
13148     size = AOP_SIZE(right);
13149     offset = 0 ;
13150
13151     while (size--) {
13152       if(!_G.resDirect)
13153         mov2f(AOP(result), AOP(right), offset);
13154       offset++;
13155     }
13156
13157     /* now depending on the sign of the destination */
13158     size = AOP_SIZE(result) - AOP_SIZE(right);
13159     /* if unsigned or not an integral type */
13160     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13161       while (size--)
13162         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13163     } else {
13164       /* we need to extend the sign :( */
13165
13166       if(size == 1) {
13167         /* Save one instruction of casting char to int */
13168         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13169         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13170         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13171       } else {
13172         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13173
13174         if(offset)
13175           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13176         else
13177           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13178         
13179         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13180
13181         while (size--)
13182           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13183       }
13184     }
13185
13186 release:
13187     pic16_freeAsmop(right,NULL,ic,TRUE);
13188     pic16_freeAsmop(result,NULL,ic,TRUE);
13189
13190 }
13191
13192 /*-----------------------------------------------------------------*/
13193 /* genDjnz - generate decrement & jump if not zero instrucion      */
13194 /*-----------------------------------------------------------------*/
13195 static int genDjnz (iCode *ic, iCode *ifx)
13196 {
13197     symbol *lbl, *lbl1;
13198     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13199
13200     if (!ifx)
13201         return 0;
13202     
13203     /* if the if condition has a false label
13204        then we cannot save */
13205     if (IC_FALSE(ifx))
13206         return 0;
13207
13208     /* if the minus is not of the form 
13209        a = a - 1 */
13210     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13211         !IS_OP_LITERAL(IC_RIGHT(ic)))
13212         return 0;
13213
13214     if (operandLitValue(IC_RIGHT(ic)) != 1)
13215         return 0;
13216
13217     /* if the size of this greater than one then no
13218        saving */
13219     if (getSize(operandType(IC_RESULT(ic))) > 1)
13220         return 0;
13221
13222     /* otherwise we can save BIG */
13223     lbl = newiTempLabel(NULL);
13224     lbl1= newiTempLabel(NULL);
13225
13226     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13227     
13228     if (IS_AOP_PREG(IC_RESULT(ic))) {
13229         pic16_emitcode("dec","%s",
13230                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13231         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13232         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13233     } else {    
13234
13235
13236       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13237       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13238
13239       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13240       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13241
13242     }
13243     
13244     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13245     ifx->generated = 1;
13246     return 1;
13247 }
13248
13249 /*-----------------------------------------------------------------*/
13250 /* genReceive - generate code for a receive iCode                  */
13251 /*-----------------------------------------------------------------*/
13252 static void genReceive (iCode *ic)
13253 {    
13254
13255   FENTRY;
13256
13257 #if 0
13258   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13259         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13260 #endif
13261 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13262
13263   if (isOperandInFarSpace(IC_RESULT(ic))
13264       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13265           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13266
13267     int size = getSize(operandType(IC_RESULT(ic)));
13268     int offset =  pic16_fReturnSizePic - size;
13269
13270       assert( 0 );
13271       while (size--) {
13272         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13273                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13274                       offset++;
13275         }
13276
13277       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13278
13279       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13280       size = AOP_SIZE(IC_RESULT(ic));
13281       offset = 0;
13282       while (size--) {
13283         pic16_emitcode ("pop","acc");
13284         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13285       }
13286   } else {
13287     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13288     _G.accInUse++;
13289     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13290     _G.accInUse--;
13291
13292     /* set pseudo stack pointer to where it should be - dw*/
13293     GpsuedoStkPtr = ic->parmBytes;
13294
13295     /* setting GpsuedoStkPtr has side effects here: */
13296     assignResultValue(IC_RESULT(ic), 0);
13297   }
13298
13299   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13300 }
13301
13302 /*-----------------------------------------------------------------*/
13303 /* genDummyRead - generate code for dummy read of volatiles        */
13304 /*-----------------------------------------------------------------*/
13305 static void
13306 genDummyRead (iCode * ic)
13307 {
13308   operand *op;
13309   int i;
13310
13311   op = IC_RIGHT(ic);
13312   if (op && IS_SYMOP(op)) {
13313     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13314       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13315       return;
13316     }
13317     pic16_aopOp (op, ic, FALSE);
13318     for (i=0; i < AOP_SIZE(op); i++) {
13319       // may need to protect this from the peepholer -- this is not nice but works...
13320       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13321       pic16_mov2w (AOP(op),i);
13322       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13323     } // for i
13324     pic16_freeAsmop (op, NULL, ic, TRUE);
13325   } else if (op) {
13326     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13327   } // if
13328 }
13329
13330 /*-----------------------------------------------------------------*/
13331 /* genpic16Code - generate code for pic16 based controllers        */
13332 /*-----------------------------------------------------------------*/
13333 /*
13334  * At this point, ralloc.c has gone through the iCode and attempted
13335  * to optimize in a way suitable for a PIC. Now we've got to generate
13336  * PIC instructions that correspond to the iCode.
13337  *
13338  * Once the instructions are generated, we'll pass through both the
13339  * peep hole optimizer and the pCode optimizer.
13340  *-----------------------------------------------------------------*/
13341
13342 void genpic16Code (iCode *lic)
13343 {
13344   iCode *ic;
13345   int cln = 0;
13346
13347     lineHead = lineCurr = NULL;
13348
13349     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13350     pic16_addpBlock(pb);
13351
13352 #if 0
13353     /* if debug information required */
13354     if (options.debug && currFunc) {
13355       if (currFunc) {
13356         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13357       }
13358     }
13359 #endif
13360
13361     for (ic = lic ; ic ; ic = ic->next ) {
13362
13363       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13364       if ( cln != ic->lineno ) {
13365         if ( options.debug ) {
13366           debugFile->writeCLine (ic);
13367         }
13368         
13369         if(!options.noCcodeInAsm) {
13370           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13371               printCLine(ic->filename, ic->lineno)));
13372         }
13373
13374         cln = ic->lineno ;
13375       }
13376         
13377       if(options.iCodeInAsm) {
13378         char *l;
13379
13380           /* insert here code to print iCode as comment */
13381           l = Safe_strdup(printILine(ic));
13382           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13383       }
13384         
13385       /* if the result is marked as
13386        * spilt and rematerializable or code for
13387        * this has already been generated then
13388        * do nothing */
13389       if (resultRemat(ic) || ic->generated ) 
13390         continue ;
13391         
13392       /* depending on the operation */
13393       switch (ic->op) {
13394         case '!' :
13395           pic16_genNot(ic);
13396           break;
13397             
13398         case '~' :
13399           pic16_genCpl(ic);
13400           break;
13401             
13402         case UNARYMINUS:
13403           genUminus (ic);
13404           break;
13405             
13406         case IPUSH:
13407           genIpush (ic);
13408           break;
13409             
13410         case IPOP:
13411           /* IPOP happens only when trying to restore a 
13412            * spilt live range, if there is an ifx statement
13413            * following this pop then the if statement might
13414            * be using some of the registers being popped which
13415            * would destroy the contents of the register so
13416            * we need to check for this condition and handle it */
13417            if (ic->next
13418              && ic->next->op == IFX
13419              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13420                genIfx (ic->next,ic);
13421           else
13422             genIpop (ic);
13423           break; 
13424             
13425         case CALL:
13426           genCall (ic);
13427           break;
13428             
13429         case PCALL:
13430           genPcall (ic);
13431           break;
13432             
13433         case FUNCTION:
13434           genFunction (ic);
13435           break;
13436             
13437         case ENDFUNCTION:
13438           genEndFunction (ic);
13439           break;
13440             
13441         case RETURN:
13442           genRet (ic);
13443           break;
13444             
13445         case LABEL:
13446           genLabel (ic);
13447           break;
13448             
13449         case GOTO:
13450           genGoto (ic);
13451           break;
13452             
13453         case '+' :
13454           pic16_genPlus (ic) ;
13455           break;
13456             
13457         case '-' :
13458           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13459             pic16_genMinus (ic);
13460           break;
13461
13462         case '*' :
13463           genMult (ic);
13464           break;
13465             
13466         case '/' :
13467           genDiv (ic) ;
13468           break;
13469             
13470         case '%' :
13471           genMod (ic);
13472           break;
13473             
13474         case '>' :
13475           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13476           break;
13477             
13478         case '<' :
13479           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13480           break;
13481             
13482         case LE_OP:
13483         case GE_OP:
13484         case NE_OP:
13485           /* note these two are xlated by algebraic equivalence
13486            * during parsing SDCC.y */
13487           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13488             "got '>=' or '<=' shouldn't have come here");
13489           break;
13490
13491         case EQ_OP:
13492           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13493           break;            
13494             
13495         case AND_OP:
13496           genAndOp (ic);
13497           break;
13498             
13499         case OR_OP:
13500           genOrOp (ic);
13501           break;
13502             
13503         case '^' :
13504           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13505           break;
13506             
13507         case '|' :
13508           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13509           break;
13510             
13511         case BITWISEAND:
13512           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13513           break;
13514             
13515         case INLINEASM:
13516           genInline (ic);
13517           break;
13518             
13519         case RRC:
13520           genRRC (ic);
13521           break;
13522             
13523         case RLC:
13524           genRLC (ic);
13525           break;
13526             
13527         case GETHBIT:
13528           genGetHbit (ic);
13529           break;
13530             
13531         case LEFT_OP:
13532           genLeftShift (ic);
13533           break;
13534             
13535         case RIGHT_OP:
13536           genRightShift (ic);
13537           break;
13538             
13539         case GET_VALUE_AT_ADDRESS:
13540           genPointerGet(ic);
13541           break;
13542             
13543         case '=' :
13544           if (POINTER_SET(ic))
13545             genPointerSet(ic);
13546           else
13547             genAssign(ic);
13548           break;
13549             
13550         case IFX:
13551           genIfx (ic,NULL);
13552           break;
13553             
13554         case ADDRESS_OF:
13555           genAddrOf (ic);
13556           break;
13557             
13558         case JUMPTABLE:
13559           genJumpTab (ic);
13560           break;
13561             
13562         case CAST:
13563           genCast (ic);
13564           break;
13565             
13566         case RECEIVE:
13567           genReceive(ic);
13568           break;
13569             
13570         case SEND:
13571           addSet(&_G.sendSet,ic);
13572           break;
13573
13574         case DUMMY_READ_VOLATILE:
13575           genDummyRead (ic);
13576           break;
13577
13578         default :
13579           ic = ic;
13580       }
13581     }
13582
13583
13584     /* now we are ready to call the
13585        peep hole optimizer */
13586     if (!options.nopeep)
13587       peepHole (&lineHead);
13588
13589     /* now do the actual printing */
13590     printLine (lineHead, codeOutFile);
13591
13592 #ifdef PCODE_DEBUG
13593     DFPRINTF((stderr,"printing pBlock\n\n"));
13594     pic16_printpBlock(stdout,pb);
13595 #endif
13596
13597     return;
13598 }
13599