* src/pic16/gen.c (genPackBits): removed deprecated warning
[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   Bug Fixes  -  Raphael Neider rneider@web.de (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
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);
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   memcpy (pcor, pc, sizeof (pCodeOpReg));
1795   pcor->r->wasUsed = 1;
1796   
1797   //pcor->pcop.type = pc->pcop.type;
1798   if(pc->pcop.name) {
1799     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1800       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1801   } else
1802     pcor->pcop.name = NULL;
1803
1804   //pcor->r = pc->r;
1805   //pcor->rIdx = pc->rIdx;
1806   //pcor->r->wasUsed=1;
1807   //pcor->instance = pc->instance;
1808
1809 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1810
1811   return PCOP(pcor);
1812 }
1813
1814 /*-----------------------------------------------------------------*/
1815 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1816 /*-----------------------------------------------------------------*/
1817 pCodeOp *pic16_popGetLit(int lit)
1818 {
1819   return pic16_newpCodeOpLit(lit);
1820 }
1821
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1826 {
1827   return pic16_newpCodeOpLit2(lit, arg2);
1828 }
1829
1830
1831 /*-----------------------------------------------------------------*/
1832 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1833 /*-----------------------------------------------------------------*/
1834 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1835 {
1836   return pic16_newpCodeOpImmd(name, offset,index, 0);
1837 }
1838
1839
1840 /*-----------------------------------------------------------------*/
1841 /* pic16_popGet - asm operator to pcode operator conversion              */
1842 /*-----------------------------------------------------------------*/
1843 pCodeOp *pic16_popGetWithString(char *str)
1844 {
1845   pCodeOp *pcop;
1846
1847
1848   if(!str) {
1849     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1850     exit (1);
1851   }
1852
1853   pcop = pic16_newpCodeOp(str,PO_STR);
1854
1855   return pcop;
1856 }
1857
1858 /*-----------------------------------------------------------------*/
1859 /* pic16_popRegFromString -                                        */
1860 /*-----------------------------------------------------------------*/
1861 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1862 {
1863
1864   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1865   pcop->type = PO_DIR;
1866
1867   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1868   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1869
1870   if(!str)
1871     str = "BAD_STRING";
1872
1873   pcop->name = Safe_calloc(1,strlen(str)+1);
1874   strcpy(pcop->name,str);
1875
1876   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1877
1878   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1879
1880   /* make sure that register doesn't exist,
1881    * and operand isn't NULL
1882    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1883   if((PCOR(pcop)->r == NULL) 
1884     && (op)
1885     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1886 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1887 //              __FUNCTION__, __LINE__, str, size, offset);
1888
1889     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1890     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1891
1892   }
1893   PCOR(pcop)->instance = offset;
1894
1895   return pcop;
1896 }
1897
1898 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1899 {
1900   pCodeOp *pcop;
1901
1902 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1903
1904         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1905         PCOR(pcop)->rIdx = rIdx;
1906         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1907
1908         PCOR(pcop)->r->isFree = 0;
1909         PCOR(pcop)->r->wasUsed = 1;
1910
1911         pcop->type = PCOR(pcop)->r->pc_type;
1912
1913   return pcop;
1914 }
1915
1916 /*---------------------------------------------------------------------------------*/
1917 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1918 /*                 VR 030601                                                       */
1919 /*---------------------------------------------------------------------------------*/
1920 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1921 {
1922   pCodeOpReg2 *pcop2;
1923   pCodeOp *temp;
1924   
1925         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1926
1927         /* comment the following check, so errors to throw up */
1928 //      if(!pcop2)return NULL;
1929
1930         temp = pic16_popGet(aop_dst, offset);
1931         pcop2->pcop2 = temp;
1932         
1933   return PCOP(pcop2);
1934 }
1935
1936
1937
1938 /*--------------------------------------------------------------------------------.-*/
1939 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1940 /*                  VR 030601 , adapted by Hans Dorn                                */
1941 /*--------------------------------------------------------------------------------.-*/
1942 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1943 {
1944   pCodeOpReg2 *pcop2;
1945  
1946         pcop2 = (pCodeOpReg2 *)src;
1947         pcop2->pcop2 = dst;
1948         
1949         return PCOP(pcop2);
1950 }
1951
1952
1953
1954 /*---------------------------------------------------------------------------------*/
1955 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1956 /*                     movff instruction                                           */
1957 /*---------------------------------------------------------------------------------*/
1958 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1959 {
1960   pCodeOpReg2 *pcop2;
1961
1962         if(!noalloc) {
1963                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1964                 pcop2->pcop2 = pic16_popCopyReg(dst);
1965         } else {
1966                 /* the pCodeOp may be already allocated */
1967                 pcop2 = (pCodeOpReg2 *)(src);
1968                 pcop2->pcop2 = (pCodeOp *)(dst);
1969         }
1970
1971   return PCOP(pcop2);
1972 }
1973
1974
1975 /*-----------------------------------------------------------------*/
1976 /* pic16_popGet - asm operator to pcode operator conversion              */
1977 /*-----------------------------------------------------------------*/
1978 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1979 {
1980   //char *s = buffer ;
1981   char *rs;
1982   pCodeOp *pcop;
1983
1984     FENTRY2;
1985     /* offset is greater than
1986     size then zero */
1987
1988 //    if (offset > (aop->size - 1) &&
1989 //        aop->type != AOP_LIT)
1990 //      return NULL;  //zero;
1991
1992     /* depending on type */
1993     switch (aop->type) {
1994         
1995     case AOP_R0:
1996     case AOP_R1:
1997     case AOP_DPTR:
1998     case AOP_DPTR2:
1999         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2000         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2001         assert( 0 );
2002         return NULL;
2003
2004
2005     case AOP_FSR0:
2006     case AOP_FSR2:
2007       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2008       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2009       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2010       PCOR(pcop)->r->wasUsed = 1;
2011       PCOR(pcop)->r->isFree = 0;
2012       
2013       PCOR(pcop)->instance = offset;
2014       pcop->type = PCOR(pcop)->r->pc_type;
2015       return (pcop);
2016
2017     case AOP_IMMD:
2018       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2019       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2020
2021     case AOP_STA:
2022       /* pCodeOp is already allocated from aopForSym */
2023         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2024         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2025           
2026       return (pcop);
2027       
2028     case AOP_ACC:
2029       {
2030         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2031
2032         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2033
2034         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2035         
2036         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2037         PCOR(pcop)->rIdx = rIdx;
2038         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2039         PCOR(pcop)->r->wasUsed=1;
2040         PCOR(pcop)->r->isFree=0;
2041
2042         PCOR(pcop)->instance = offset;
2043         pcop->type = PCOR(pcop)->r->pc_type;
2044 //      rs = aop->aopu.aop_reg[offset]->name;
2045 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2046         return pcop;
2047
2048
2049 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2050 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2051
2052 //      assert( 0 );
2053       }
2054         
2055     case AOP_DIR:
2056       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2057       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2058         
2059 #if 0
2060     case AOP_PAGED:
2061       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2062       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2063 #endif
2064
2065     case AOP_REG:
2066       {
2067         int rIdx;
2068         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2069         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2070
2071         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2072         
2073         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2074 //      pcop->type = PO_GPR_REGISTER;
2075         PCOR(pcop)->rIdx = rIdx;
2076         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2077         PCOR(pcop)->r->wasUsed=1;
2078         PCOR(pcop)->r->isFree=0;
2079
2080         PCOR(pcop)->instance = offset;
2081         pcop->type = PCOR(pcop)->r->pc_type;
2082         
2083         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2084         rs = aop->aopu.aop_reg[offset]->name;
2085         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2086         return pcop;
2087       }
2088
2089     case AOP_CRY:
2090         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2091
2092       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2093       PCOR(pcop)->instance = offset;
2094       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2095       //if(PCOR(pcop)->r == NULL)
2096       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2097       return pcop;
2098         
2099     case AOP_LIT:
2100         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2101       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2102
2103     case AOP_STR:
2104       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2105       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2106
2107       /*
2108       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2109       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2110       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2111       pcop->type = PCOR(pcop)->r->pc_type;
2112       pcop->name = PCOR(pcop)->r->name;
2113
2114       return pcop;
2115       */
2116
2117     case AOP_PCODE:
2118       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2119                           __LINE__, 
2120                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2121       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2122       switch( aop->aopu.pcop->type ) {
2123         case PO_DIR: PCOR(pcop)->instance += offset; break;
2124         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2125         case PO_WREG:
2126             assert (offset==0);
2127             break;
2128         default:
2129           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2130           assert( 0 );  /* should never reach here */;
2131       }
2132       return pcop;
2133     }
2134
2135     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2136            "pic16_popGet got unsupported aop->type");
2137     exit(0);
2138 }
2139 /*-----------------------------------------------------------------*/
2140 /* pic16_aopPut - puts a string for a aop                                */
2141 /*-----------------------------------------------------------------*/
2142 void pic16_aopPut (asmop *aop, char *s, int offset)
2143 {
2144     char *d = buffer ;
2145     symbol *lbl ;
2146
2147     return;
2148
2149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2150
2151     if (aop->size && offset > ( aop->size - 1)) {
2152         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2153                "pic16_aopPut got offset > aop->size");
2154         exit(0);
2155     }
2156
2157     /* will assign value to value */
2158     /* depending on where it is ofcourse */
2159     switch (aop->type) {
2160     case AOP_DIR:
2161       if (offset) {
2162         sprintf(d,"(%s + %d)",
2163                 aop->aopu.aop_dir,offset);
2164         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2165
2166       } else
2167             sprintf(d,"%s",aop->aopu.aop_dir);
2168         
2169         if (strcmp(d,s)) {
2170           DEBUGpic16_emitcode(";","%d",__LINE__);
2171           if(strcmp(s,"W"))
2172             pic16_emitcode("movf","%s,w",s);
2173           pic16_emitcode("movwf","%s",d);
2174
2175           if(strcmp(s,"W")) {
2176             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2177             if(offset >= aop->size) {
2178               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2179               break;
2180             } else
2181               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2182           }
2183
2184           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2185
2186
2187         }
2188         break;
2189         
2190     case AOP_REG:
2191       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2192         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2193           /*
2194             if (*s == '@'           ||
2195                 strcmp(s,"r0") == 0 ||
2196                 strcmp(s,"r1") == 0 ||
2197                 strcmp(s,"r2") == 0 ||
2198                 strcmp(s,"r3") == 0 ||
2199                 strcmp(s,"r4") == 0 ||
2200                 strcmp(s,"r5") == 0 ||
2201                 strcmp(s,"r6") == 0 || 
2202                 strcmp(s,"r7") == 0 )
2203                 pic16_emitcode("mov","%s,%s  ; %d",
2204                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2205             else
2206           */
2207
2208           if(strcmp(s,"W")==0 )
2209             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2210
2211           pic16_emitcode("movwf","%s",
2212                    aop->aopu.aop_reg[offset]->name);
2213
2214           if(strcmp(s,zero)==0) {
2215             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2216
2217           } else if(strcmp(s,"W")==0) {
2218             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2219             pcop->type = PO_GPR_REGISTER;
2220
2221             PCOR(pcop)->rIdx = -1;
2222             PCOR(pcop)->r = NULL;
2223
2224             DEBUGpic16_emitcode(";","%d",__LINE__);
2225             pcop->name = Safe_strdup(s);
2226             pic16_emitpcode(POC_MOVFW,pcop);
2227             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2228           } else if(strcmp(s,one)==0) {
2229             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2230             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2231           } else {
2232             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2233           }
2234         }
2235         break;
2236         
2237     case AOP_DPTR:
2238     case AOP_DPTR2:
2239     
2240     if (aop->type == AOP_DPTR2)
2241     {
2242         genSetDPTR(1);
2243     }
2244     
2245         if (aop->code) {
2246             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2247                    "pic16_aopPut writting to code space");
2248             exit(0);
2249         }
2250         
2251         while (offset > aop->coff) {
2252             aop->coff++;
2253             pic16_emitcode ("inc","dptr");
2254         }
2255         
2256         while (offset < aop->coff) {
2257             aop->coff-- ;
2258             pic16_emitcode("lcall","__decdptr");
2259         }
2260         
2261         aop->coff = offset;
2262         
2263         /* if not in accumulater */
2264         MOVA(s);        
2265         
2266         pic16_emitcode ("movx","@dptr,a");
2267         
2268     if (aop->type == AOP_DPTR2)
2269     {
2270         genSetDPTR(0);
2271     }
2272         break;
2273         
2274     case AOP_R0:
2275     case AOP_R1:
2276         while (offset > aop->coff) {
2277             aop->coff++;
2278             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2279         }
2280         while (offset < aop->coff) {
2281             aop->coff-- ;
2282             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2283         }
2284         aop->coff = offset;
2285         
2286         if (aop->paged) {
2287             MOVA(s);           
2288             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2289             
2290         } else
2291             if (*s == '@') {
2292                 MOVA(s);
2293                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2294             } else
2295                 if (strcmp(s,"r0") == 0 ||
2296                     strcmp(s,"r1") == 0 ||
2297                     strcmp(s,"r2") == 0 ||
2298                     strcmp(s,"r3") == 0 ||
2299                     strcmp(s,"r4") == 0 ||
2300                     strcmp(s,"r5") == 0 ||
2301                     strcmp(s,"r6") == 0 || 
2302                     strcmp(s,"r7") == 0 ) {
2303                     char buffer[10];
2304                     sprintf(buffer,"a%s",s);
2305                     pic16_emitcode("mov","@%s,%s",
2306                              aop->aopu.aop_ptr->name,buffer);
2307                 } else
2308                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2309         
2310         break;
2311         
2312     case AOP_STK:
2313         if (strcmp(s,"a") == 0)
2314             pic16_emitcode("push","acc");
2315         else
2316             pic16_emitcode("push","%s",s);
2317         
2318         break;
2319         
2320     case AOP_CRY:
2321         /* if bit variable */
2322         if (!aop->aopu.aop_dir) {
2323             pic16_emitcode("clr","a");
2324             pic16_emitcode("rlc","a");
2325         } else {
2326             if (s == zero) 
2327                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2328             else
2329                 if (s == one)
2330                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2331                 else
2332                     if (!strcmp(s,"c"))
2333                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2334                     else {
2335                         lbl = newiTempLabel(NULL);
2336                         
2337                         if (strcmp(s,"a")) {
2338                             MOVA(s);
2339                         }
2340                         pic16_emitcode("clr","c");
2341                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2342                         pic16_emitcode("cpl","c");
2343                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2344                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2345                     }
2346         }
2347         break;
2348         
2349     case AOP_STR:
2350         aop->coff = offset;
2351         if (strcmp(aop->aopu.aop_str[offset],s))
2352             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2353         break;
2354         
2355     case AOP_ACC:
2356         aop->coff = offset;
2357         if (!offset && (strcmp(s,"acc") == 0))
2358             break;
2359         
2360         if (strcmp(aop->aopu.aop_str[offset],s))
2361             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2362         break;
2363
2364     default :
2365         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2366 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2367 //             "pic16_aopPut got unsupported aop->type");
2368 //      exit(0);    
2369     }    
2370
2371 }
2372
2373 /*-----------------------------------------------------------------*/
2374 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2375 /*-----------------------------------------------------------------*/
2376 void pic16_mov2w (asmop *aop, int offset)
2377 {
2378   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2379
2380   if(is_LitAOp(aop))
2381     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2382   else
2383     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2384 }
2385
2386 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2387 {
2388   if(is_LitAOp(src)) {
2389     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2390     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2391   } else {
2392     if(pic16_sameRegsOfs(src, dst, offset))return;
2393     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2394                       pic16_popGet(dst, offset)));
2395   }
2396 }
2397
2398 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2399 {
2400   if(is_LitAOp(src)) {
2401     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2402     pic16_emitpcode(POC_MOVWF, dst);
2403   } else {
2404     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2405   }
2406 }
2407
2408 void pic16_testStackOverflow(void)
2409 {
2410 #define GSTACK_TEST_NAME        "_gstack_test"
2411
2412   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2413   
2414   {
2415     symbol *sym;
2416
2417       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2418       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2419 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2420       checkAddSym(&externs, sym);
2421   }
2422
2423 }
2424
2425 /* push pcop into stack */
2426 void pic16_pushpCodeOp(pCodeOp *pcop)
2427 {
2428 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2429   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2430   if(pic16_options.gstack)
2431     pic16_testStackOverflow();
2432     
2433 }
2434
2435 /* pop pcop from stack */
2436 void pic16_poppCodeOp(pCodeOp *pcop)
2437 {
2438   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2439   if(pic16_options.gstack)
2440     pic16_testStackOverflow();
2441 }
2442
2443
2444 /*-----------------------------------------------------------------*/
2445 /* pushw - pushes wreg to stack                                    */
2446 /*-----------------------------------------------------------------*/
2447 void pushw(void)
2448 {
2449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2450   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2451   if(pic16_options.gstack)
2452     pic16_testStackOverflow();
2453 }
2454
2455                 
2456 /*-----------------------------------------------------------------*/
2457 /* pushaop - pushes aop to stack                                   */
2458 /*-----------------------------------------------------------------*/
2459 void pushaop(asmop *aop, int offset)
2460 {
2461   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2462
2463   if(is_LitAOp(aop)) {
2464     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2465     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2466   } else {
2467     pic16_emitpcode(POC_MOVFF,
2468       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2469   }
2470
2471   if(pic16_options.gstack)
2472     pic16_testStackOverflow();
2473 }
2474
2475 /*-----------------------------------------------------------------*/
2476 /* popaop - pops aop from stack                                    */
2477 /*-----------------------------------------------------------------*/
2478 void popaop(asmop *aop, int offset)
2479 {
2480   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2481   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2482   if(pic16_options.gstack)
2483     pic16_testStackOverflow();
2484 }
2485
2486 void popaopidx(asmop *aop, int offset, int index)
2487 {
2488   int ofs=1;
2489
2490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2491
2492     if(STACK_MODEL_LARGE)ofs++;
2493
2494     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2495     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2496     if(pic16_options.gstack)
2497       pic16_testStackOverflow();
2498 }
2499
2500 #if !(USE_GENERIC_SIGNED_SHIFT)
2501 /*-----------------------------------------------------------------*/
2502 /* reAdjustPreg - points a register back to where it should        */
2503 /*-----------------------------------------------------------------*/
2504 static void reAdjustPreg (asmop *aop)
2505 {
2506     int size ;
2507
2508     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2509     aop->coff = 0;
2510     if ((size = aop->size) <= 1)
2511         return ;
2512     size-- ;
2513     switch (aop->type) {
2514         case AOP_R0 :
2515         case AOP_R1 :
2516             while (size--)
2517                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2518             break;          
2519         case AOP_DPTR :
2520         case AOP_DPTR2:
2521             if (aop->type == AOP_DPTR2)
2522             {
2523                 genSetDPTR(1);
2524             } 
2525             while (size--)
2526             {
2527                 pic16_emitcode("lcall","__decdptr");
2528             }
2529                 
2530             if (aop->type == AOP_DPTR2)
2531             {
2532                 genSetDPTR(0);
2533             }                
2534             break;  
2535
2536     }   
2537
2538 }
2539 #endif
2540
2541 #if 0
2542 /*-----------------------------------------------------------------*/
2543 /* opIsGptr: returns non-zero if the passed operand is             */   
2544 /* a generic pointer type.                                         */
2545 /*-----------------------------------------------------------------*/ 
2546 static int opIsGptr(operand *op)
2547 {
2548     sym_link *type = operandType(op);
2549     
2550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2551     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2552     {
2553         return 1;
2554     }
2555     return 0;        
2556 }
2557 #endif
2558
2559 /*-----------------------------------------------------------------*/
2560 /* pic16_getDataSize - get the operand data size                         */
2561 /*-----------------------------------------------------------------*/
2562 int pic16_getDataSize(operand *op)
2563 {
2564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2565
2566
2567     return AOP_SIZE(op);
2568
2569     // tsd- in the pic port, the genptr size is 1, so this code here
2570     // fails. ( in the 8051 port, the size was 4).
2571 #if 0
2572     int size;
2573     size = AOP_SIZE(op);
2574     if (size == GPTRSIZE)
2575     {
2576         sym_link *type = operandType(op);
2577         if (IS_GENPTR(type))
2578         {
2579             /* generic pointer; arithmetic operations
2580              * should ignore the high byte (pointer type).
2581              */
2582             size--;
2583     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2584         }
2585     }
2586     return size;
2587 #endif
2588 }
2589
2590 /*-----------------------------------------------------------------*/
2591 /* pic16_outAcc - output Acc                                             */
2592 /*-----------------------------------------------------------------*/
2593 void pic16_outAcc(operand *result)
2594 {
2595   int size,offset;
2596   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2597   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2598
2599
2600   size = pic16_getDataSize(result);
2601   if(size){
2602     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2603     size--;
2604     offset = 1;
2605     /* unsigned or positive */
2606     while(size--)
2607       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2608   }
2609
2610 }
2611
2612 /*-----------------------------------------------------------------*/
2613 /* pic16_outBitC - output a bit C                                  */
2614 /*                 Move to result the value of Carry flag -- VR    */
2615 /*-----------------------------------------------------------------*/
2616 void pic16_outBitC(operand *result)
2617 {
2618   int i;
2619
2620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2621
2622     /* if the result is bit */
2623     if (AOP_TYPE(result) == AOP_CRY) {
2624         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2625         pic16_aopPut(AOP(result),"c",0);
2626     } else {
2627
2628         i = AOP_SIZE(result);
2629         while(i--) {
2630                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2631         }
2632         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2633     }
2634 }
2635
2636 /*-----------------------------------------------------------------*/
2637 /* pic16_outBitOp - output a bit from Op                           */
2638 /*                 Move to result the value of set/clr op -- VR    */
2639 /*-----------------------------------------------------------------*/
2640 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2641 {
2642   int i;
2643
2644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2645
2646     /* if the result is bit */
2647     if (AOP_TYPE(result) == AOP_CRY) {
2648         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2649         pic16_aopPut(AOP(result),"c",0);
2650     } else {
2651
2652         i = AOP_SIZE(result);
2653         while(i--) {
2654                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2655         }
2656         pic16_emitpcode(POC_RRCF, pcop);          
2657         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2658     }
2659 }
2660
2661 /*-----------------------------------------------------------------*/
2662 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2663 /*-----------------------------------------------------------------*/
2664 void pic16_toBoolean(operand *oper)
2665 {
2666     int size = AOP_SIZE(oper) - 1;
2667     int offset = 1;
2668
2669     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2670
2671     if ( AOP_TYPE(oper) != AOP_ACC) {
2672       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2673     }
2674     while (size--) {
2675       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2676     }
2677 }
2678
2679
2680 #if !defined(GEN_Not)
2681 /*-----------------------------------------------------------------*/
2682 /* genNot - generate code for ! operation                          */
2683 /*-----------------------------------------------------------------*/
2684 static void pic16_genNot (iCode *ic)
2685 {
2686   symbol *tlbl;
2687   int size;
2688
2689   FENTRY;
2690   /* assign asmOps to operand & result */
2691   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2692   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2693
2694   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2695   /* if in bit space then a special case */
2696   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2697     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2698       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2699       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2700     } else {
2701       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2702       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2703       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704     }
2705     goto release;
2706   }
2707
2708   size = AOP_SIZE(IC_LEFT(ic));
2709   if(size == 1) {
2710     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2711     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2712     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2713     goto release;
2714   }
2715   pic16_toBoolean(IC_LEFT(ic));
2716
2717   tlbl = newiTempLabel(NULL);
2718   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2719   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2720   pic16_outBitC(IC_RESULT(ic));
2721
2722  release:    
2723   /* release the aops */
2724   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2725   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2726 }
2727 #endif
2728
2729
2730 #if !defined(GEN_Cpl)
2731 /*-----------------------------------------------------------------*/
2732 /* genCpl - generate code for complement                           */
2733 /*-----------------------------------------------------------------*/
2734 static void pic16_genCpl (iCode *ic)
2735 {
2736   int offset = 0;
2737   int size ;
2738
2739     FENTRY;
2740     /* assign asmOps to operand & result */
2741     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2742     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2743
2744     /* if both are in bit space then 
2745     a special case */
2746     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2747         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2748
2749         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2750         pic16_emitcode("cpl","c"); 
2751         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2752         goto release; 
2753     } 
2754
2755     size = AOP_SIZE(IC_RESULT(ic));
2756     while (size--) {
2757 /*
2758         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2759         MOVA(l);       
2760         pic16_emitcode("cpl","a");
2761         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2762 */
2763         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2764               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2765         } else {
2766                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2767                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2768         }
2769         offset++;
2770
2771     }
2772
2773
2774 release:
2775     /* release the aops */
2776     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2777     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2778 }
2779 #endif
2780
2781 /*-----------------------------------------------------------------*/
2782 /* genUminusFloat - unary minus for floating points                */
2783 /*-----------------------------------------------------------------*/
2784 static void genUminusFloat(operand *op,operand *result)
2785 {
2786   int size ,offset =0 ;
2787   
2788     FENTRY;
2789     /* for this we just need to flip the 
2790     first it then copy the rest in place */
2791     size = AOP_SIZE(op);
2792
2793     while(size--) {
2794       pic16_mov2f(AOP(result), AOP(op), offset);
2795       offset++;
2796     }
2797     
2798     /* toggle the MSB's highest bit */
2799     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2800 }
2801
2802 /*-----------------------------------------------------------------*/
2803 /* genUminus - unary minus code generation                         */
2804 /*-----------------------------------------------------------------*/
2805 static void genUminus (iCode *ic)
2806 {
2807   int size, i;
2808   sym_link *optype, *rtype;
2809   symbol *label;
2810   int needLabel=0;
2811
2812     FENTRY;     
2813     
2814     /* assign asmops */
2815     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2816     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2817
2818     /* if both in bit space then special case */
2819     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2820       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2821         
2822         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2823         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2824         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2825         goto release; 
2826     } 
2827
2828     optype = operandType(IC_LEFT(ic));
2829     rtype = operandType(IC_RESULT(ic));
2830
2831     /* if float then do float stuff */
2832     if (IS_FLOAT(optype)) {
2833       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2834       goto release;
2835     }
2836
2837     /* otherwise subtract from zero by taking the 2's complement */
2838     size = AOP_SIZE(IC_LEFT(ic));
2839     label = newiTempLabel ( NULL );
2840     
2841     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2842       for (i=size-1; i > 0; i--) {
2843         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2844       } // for
2845       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2846       for (i=1; i < size; i++) {
2847         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2848         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2849       } // for
2850     } else {
2851       for (i=size-1; i >= 0; i--) {
2852         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2853         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2854       } // for
2855       if (size > 1) {
2856         for (i=0; i < size-2; i++) {
2857           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2858           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2859         } // for
2860         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2861       } // if
2862       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2863     }
2864     if (needLabel)
2865       pic16_emitpLabel (label->key);
2866
2867 release:
2868     /* release the aops */
2869     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2870     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2871 }
2872
2873 #if 0
2874 /*-----------------------------------------------------------------*/
2875 /* saveRegisters - will look for a call and save the registers     */
2876 /*-----------------------------------------------------------------*/
2877 static void saveRegisters(iCode *lic) 
2878 {
2879     int i;
2880     iCode *ic;
2881     bitVect *rsave;
2882     sym_link *dtype;
2883
2884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2885     /* look for call */
2886     for (ic = lic ; ic ; ic = ic->next) 
2887         if (ic->op == CALL || ic->op == PCALL)
2888             break;
2889
2890     if (!ic) {
2891         fprintf(stderr,"found parameter push with no function call\n");
2892         return ;
2893     }
2894
2895     /* if the registers have been saved already then
2896     do nothing */
2897     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2898         return ;
2899
2900     /* find the registers in use at this time 
2901     and push them away to safety */
2902     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2903                           ic->rUsed);
2904
2905     ic->regsSaved = 1;
2906     if (options.useXstack) {
2907         if (bitVectBitValue(rsave,R0_IDX))
2908             pic16_emitcode("mov","b,r0");
2909         pic16_emitcode("mov","r0,%s",spname);
2910         for (i = 0 ; i < pic16_nRegs ; i++) {
2911             if (bitVectBitValue(rsave,i)) {
2912                 if (i == R0_IDX)
2913                     pic16_emitcode("mov","a,b");
2914                 else
2915                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2916                 pic16_emitcode("movx","@r0,a");
2917                 pic16_emitcode("inc","r0");
2918             }
2919         }
2920         pic16_emitcode("mov","%s,r0",spname);
2921         if (bitVectBitValue(rsave,R0_IDX))
2922             pic16_emitcode("mov","r0,b");           
2923     }// else
2924     //for (i = 0 ; i < pic16_nRegs ; i++) {
2925     //    if (bitVectBitValue(rsave,i))
2926     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2927     //}
2928
2929     dtype = operandType(IC_LEFT(ic));
2930     if (currFunc && dtype && 
2931         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2932         IFFUNC_ISISR(currFunc->type) &&
2933         !ic->bankSaved) 
2934
2935         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2936
2937 }
2938 /*-----------------------------------------------------------------*/
2939 /* unsaveRegisters - pop the pushed registers                      */
2940 /*-----------------------------------------------------------------*/
2941 static void unsaveRegisters (iCode *ic)
2942 {
2943     int i;
2944     bitVect *rsave;
2945
2946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2947     /* find the registers in use at this time 
2948     and push them away to safety */
2949     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2950                           ic->rUsed);
2951     
2952     if (options.useXstack) {
2953         pic16_emitcode("mov","r0,%s",spname);   
2954         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2955             if (bitVectBitValue(rsave,i)) {
2956                 pic16_emitcode("dec","r0");
2957                 pic16_emitcode("movx","a,@r0");
2958                 if (i == R0_IDX)
2959                     pic16_emitcode("mov","b,a");
2960                 else
2961                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2962             }       
2963
2964         }
2965         pic16_emitcode("mov","%s,r0",spname);
2966         if (bitVectBitValue(rsave,R0_IDX))
2967             pic16_emitcode("mov","r0,b");
2968     } //else
2969     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2970     //    if (bitVectBitValue(rsave,i))
2971     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2972     //}
2973
2974 }  
2975 #endif
2976
2977 #if 0  // patch 14
2978 /*-----------------------------------------------------------------*/
2979 /* pushSide -                                                      */
2980 /*-----------------------------------------------------------------*/
2981 static void pushSide(operand * oper, int size)
2982 {
2983         int offset = 0;
2984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2985         while (size--) {
2986                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2987                 if (AOP_TYPE(oper) != AOP_REG &&
2988                     AOP_TYPE(oper) != AOP_DIR &&
2989                     strcmp(l,"a") ) {
2990                         pic16_emitcode("mov","a,%s",l);
2991                         pic16_emitcode("push","acc");
2992                 } else
2993                         pic16_emitcode("push","%s",l);
2994         }
2995 }
2996 #endif // patch 14
2997
2998 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2999 {
3000   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3001     pic16_emitpcode(POC_MOVFW, src);
3002     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3003   } else {
3004     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3005         src, pic16_popGet(AOP(op), offset)));
3006   }
3007 }
3008
3009
3010 /*-----------------------------------------------------------------*/
3011 /* assignResultValue - assign results to oper, rescall==1 is       */
3012 /*                     called from genCall() or genPcall()         */
3013 /*-----------------------------------------------------------------*/
3014 static void assignResultValue(operand * oper, int rescall)
3015 {
3016   int size = AOP_SIZE(oper);
3017   int offset=0;
3018   
3019     FENTRY2;
3020 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3021     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3022
3023     if(rescall) {
3024       /* assign result from a call/pcall function() */
3025                 
3026       /* function results are stored in a special order,
3027        * see top of file with Function return policy, or manual */
3028
3029       if(size <= 4) {
3030         /* 8-bits, result in WREG */
3031         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3032                         
3033         if(size>1) {
3034           /* 16-bits, result in PRODL:WREG */
3035           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3036         }
3037                         
3038         if(size>2) {
3039           /* 24-bits, result in PRODH:PRODL:WREG */
3040           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3041         }
3042                         
3043         if(size>3) {
3044           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3045           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3046         }
3047       
3048       } else {
3049         /* >32-bits, result on stack, and FSR0 points to beginning.
3050          * Fix stack when done */
3051         /* FIXME FIXME */
3052 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3053         while (size--) {
3054 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3055 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3056                 
3057           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3058           GpsuedoStkPtr++;
3059         }
3060                         
3061         /* fix stack */
3062         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3063         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3064         if(STACK_MODEL_LARGE) {
3065           emitSKPNC;
3066           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3067         }
3068       }                 
3069     } else {
3070       int areg = 0;             /* matching argument register */
3071       
3072 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3073       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3074
3075
3076       /* its called from genReceive (probably) -- VR */
3077       /* I hope this code will not be called from somewhere else in the future! 
3078        * We manually set the pseudo stack pointer in genReceive. - dw
3079        */
3080       if(!GpsuedoStkPtr && _G.useWreg) {
3081 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3082
3083         /* The last byte in the assignment is in W */
3084         if(areg <= GpsuedoStkPtr) {
3085           size--;
3086           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3087           offset++;
3088 //          debugf("receive from WREG\n", 0);
3089         }
3090         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3091       }
3092 //      GpsuedoStkPtr++;
3093       _G.stack_lat = AOP_SIZE(oper)-1;
3094
3095       while (size) {
3096         size--;
3097         GpsuedoStkPtr++;
3098         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3099 //        debugf("receive from STACK\n", 0);
3100         offset++;
3101       }
3102     }
3103 }
3104
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genIpush - generate code for pushing this gets a little complex */
3108 /*-----------------------------------------------------------------*/
3109 static void genIpush (iCode *ic)
3110 {
3111 //  int size, offset=0;
3112
3113   FENTRY;
3114   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3115
3116   if(ic->parmPush) {
3117     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3118
3119     /* send to stack as normal */
3120     addSet(&_G.sendSet,ic);
3121 //    addSetHead(&_G.sendSet,ic);
3122     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3123   }
3124
3125         
3126 #if 0
3127     int size, offset = 0 ;
3128     char *l;
3129
3130
3131     /* if this is not a parm push : ie. it is spill push 
3132     and spill push is always done on the local stack */
3133     if (!ic->parmPush) {
3134
3135         /* and the item is spilt then do nothing */
3136         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3137             return ;
3138
3139         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3140         size = AOP_SIZE(IC_LEFT(ic));
3141         /* push it on the stack */
3142         while(size--) {
3143             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3144             if (*l == '#') {
3145                 MOVA(l);
3146                 l = "acc";
3147             }
3148             pic16_emitcode("push","%s",l);
3149         }
3150         return ;        
3151     }
3152
3153     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3154 #endif
3155 }
3156
3157 /*-----------------------------------------------------------------*/
3158 /* genIpop - recover the registers: can happen only for spilling   */
3159 /*-----------------------------------------------------------------*/
3160 static void genIpop (iCode *ic)
3161 {
3162   FENTRY;
3163   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3164 #if 0
3165     int size,offset ;
3166
3167
3168     /* if the temp was not pushed then */
3169     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3170         return ;
3171
3172     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3173     size = AOP_SIZE(IC_LEFT(ic));
3174     offset = (size-1);
3175     while (size--) 
3176         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3177                                    FALSE,TRUE));
3178
3179     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3180 #endif
3181 }
3182
3183 #if 0
3184 /*-----------------------------------------------------------------*/
3185 /* unsaverbank - restores the resgister bank from stack            */
3186 /*-----------------------------------------------------------------*/
3187 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3188 {
3189   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3190 #if 0
3191     int i;
3192     asmop *aop ;
3193     regs *r = NULL;
3194
3195     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3196     if (popPsw) {
3197         if (options.useXstack) {
3198             aop = newAsmop(0);
3199             r = getFreePtr(ic,&aop,FALSE);
3200             
3201             
3202             pic16_emitcode("mov","%s,_spx",r->name);
3203             pic16_emitcode("movx","a,@%s",r->name);
3204             pic16_emitcode("mov","psw,a");
3205             pic16_emitcode("dec","%s",r->name);
3206             
3207         }else
3208             pic16_emitcode ("pop","psw");
3209     }
3210
3211     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3212         if (options.useXstack) {       
3213             pic16_emitcode("movx","a,@%s",r->name);
3214             //pic16_emitcode("mov","(%s+%d),a",
3215             //       regspic16[i].base,8*bank+regspic16[i].offset);
3216             pic16_emitcode("dec","%s",r->name);
3217
3218         } else 
3219           pic16_emitcode("pop",""); //"(%s+%d)",
3220         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3221     }
3222
3223     if (options.useXstack) {
3224
3225         pic16_emitcode("mov","_spx,%s",r->name);
3226         pic16_freeAsmop(NULL,aop,ic,TRUE);
3227
3228     }
3229 #endif 
3230 }
3231
3232 /*-----------------------------------------------------------------*/
3233 /* saverbank - saves an entire register bank on the stack          */
3234 /*-----------------------------------------------------------------*/
3235 static void saverbank (int bank, iCode *ic, bool pushPsw)
3236 {
3237   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3238 #if 0
3239     int i;
3240     asmop *aop ;
3241     regs *r = NULL;
3242
3243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3244     if (options.useXstack) {
3245
3246         aop = newAsmop(0);
3247         r = getFreePtr(ic,&aop,FALSE);  
3248         pic16_emitcode("mov","%s,_spx",r->name);
3249
3250     }
3251
3252     for (i = 0 ; i < pic16_nRegs ;i++) {
3253         if (options.useXstack) {
3254             pic16_emitcode("inc","%s",r->name);
3255             //pic16_emitcode("mov","a,(%s+%d)",
3256             //         regspic16[i].base,8*bank+regspic16[i].offset);
3257             pic16_emitcode("movx","@%s,a",r->name);           
3258         } else 
3259           pic16_emitcode("push","");// "(%s+%d)",
3260                      //regspic16[i].base,8*bank+regspic16[i].offset);
3261     }
3262     
3263     if (pushPsw) {
3264         if (options.useXstack) {
3265             pic16_emitcode("mov","a,psw");
3266             pic16_emitcode("movx","@%s,a",r->name);     
3267             pic16_emitcode("inc","%s",r->name);
3268             pic16_emitcode("mov","_spx,%s",r->name);       
3269             pic16_freeAsmop (NULL,aop,ic,TRUE);
3270             
3271         } else
3272             pic16_emitcode("push","psw");
3273         
3274         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3275     }
3276     ic->bankSaved = 1;
3277 #endif
3278 }
3279 #endif  /* 0 */
3280
3281
3282 static int wparamCmp(void *p1, void *p2)
3283 {
3284   return (!strcmp((char *)p1, (char *)p2));
3285 }
3286
3287 int inWparamList(char *s)
3288 {
3289   return isinSetWith(wparamList, s, wparamCmp);
3290
3291
3292
3293 /*-----------------------------------------------------------------*/
3294 /* genCall - generates a call statement                            */
3295 /*-----------------------------------------------------------------*/
3296 static void genCall (iCode *ic)
3297 {
3298   sym_link *ftype;   
3299   int stackParms=0;
3300   int use_wreg=0;
3301   int inwparam=0;
3302   char *fname;
3303   
3304     FENTRY;
3305
3306     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3307     /* if caller saves & we have not saved then */
3308 //    if (!ic->regsSaved)
3309 //      saveRegisters(ic);
3310
3311         /* initialise stackParms for IPUSH pushes */
3312 //      stackParms = psuedoStkPtr;
3313 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3314     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3315     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3316
3317 #if 0
3318     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3319 #endif
3320
3321     /* if send set is not empty the assign */
3322     if (_G.sendSet) {
3323       iCode *sic;
3324       int psuedoStkPtr=-1; 
3325       int firstTimeThruLoop = 1;
3326
3327
3328         /* reverse sendSet if function is not reentrant */
3329         if(!IFFUNC_ISREENT(ftype))
3330           _G.sendSet = reverseSet(_G.sendSet);
3331
3332         /* First figure how many parameters are getting passed */
3333         stackParms = 0;
3334         use_wreg = 0;
3335         
3336         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3337           int size;
3338 //          int offset = 0;
3339
3340             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3341             size = AOP_SIZE(IC_LEFT(sic));
3342
3343             stackParms += size;
3344
3345             /* pass the last byte through WREG */
3346             if(inwparam) {
3347
3348               while (size--) {
3349                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3350                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3351                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3352
3353                 if(!firstTimeThruLoop) {
3354                   /* If this is not the first time we've been through the loop
3355                    * then we need to save the parameter in a temporary
3356                    * register. The last byte of the last parameter is
3357                    * passed in W. */
3358
3359                   pushw();
3360 //                  --psuedoStkPtr;             // sanity check
3361                   use_wreg = 1;
3362                 }
3363                 
3364                 firstTimeThruLoop=0;
3365
3366                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3367
3368 //                offset++;
3369               }
3370             } else {
3371               /* all arguments are passed via stack */
3372               use_wreg = 0;
3373
3374               while (size--) {
3375                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3376                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3377                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3378
3379 //                pushaop(AOP(IC_LEFT(sic)), size);
3380                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3381
3382                 if(!_G.resDirect)
3383                   pushw();
3384               }
3385             }
3386
3387             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3388           }
3389
3390           if(inwparam) {
3391             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3392               pushw();  /* save last parameter to stack if functions has varargs */
3393               use_wreg = 0;
3394             } else
3395               use_wreg = 1;
3396           } else use_wreg = 0;
3397
3398           _G.stackRegSet = _G.sendSet;
3399           _G.sendSet = NULL;
3400     }
3401
3402     /* make the call */
3403     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3404
3405     GpsuedoStkPtr=0;
3406     
3407     /* if we need to assign a result value */
3408     if ((IS_ITEMP(IC_RESULT(ic))
3409           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3410               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3411         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3412
3413       _G.accInUse++;
3414       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3415       _G.accInUse--;
3416
3417       assignResultValue(IC_RESULT(ic), 1);
3418
3419       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3421                 
3422       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3423     }
3424
3425     if(!stackParms && ic->parmBytes) {
3426       stackParms = ic->parmBytes;
3427     }
3428       
3429     stackParms -= use_wreg;
3430     
3431     if(stackParms>0) {
3432       if(stackParms == 1) {
3433         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3434       } else {
3435         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3436         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3437       }
3438       if(STACK_MODEL_LARGE) {
3439         emitSKPNC;
3440         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3441       }
3442     }
3443
3444 #if 0
3445     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3446 #endif
3447
3448     /* adjust the stack for parameters if required */
3449 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3450
3451 #if 0
3452       /* if register bank was saved then pop them */
3453       if (ic->bankSaved)
3454         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3455
3456       /* if we hade saved some registers then unsave them */
3457       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3458         unsaveRegisters (ic);
3459 #endif
3460 }
3461
3462
3463
3464 /*-----------------------------------------------------------------*/
3465 /* genPcall - generates a call by pointer statement                */
3466 /*            new version, created from genCall - HJD              */
3467 /*-----------------------------------------------------------------*/
3468 static void genPcall (iCode *ic)
3469 {
3470   sym_link *ftype, *fntype;
3471   int stackParms=0;
3472   symbol *retlbl = newiTempLabel(NULL);
3473   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3474   
3475     FENTRY;
3476
3477     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3478     fntype = operandType( IC_LEFT(ic) )->next;
3479
3480     /* if send set is not empty the assign */
3481     if (_G.sendSet) {
3482       iCode *sic;
3483       int psuedoStkPtr=-1; 
3484
3485       /* reverse sendSet if function is not reentrant */
3486       if(!IFFUNC_ISREENT(fntype))
3487         _G.sendSet = reverseSet(_G.sendSet);
3488
3489       stackParms = 0;
3490       
3491       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3492         int size;
3493
3494           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3495           size = AOP_SIZE(IC_LEFT(sic));
3496           stackParms += size;
3497
3498           /* all parameters are passed via stack, since WREG is clobbered
3499            * by the calling sequence */
3500           while (size--) {
3501             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3502             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3503             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3504
3505             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3506             pushw();
3507           }
3508
3509           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3510       }
3511
3512       _G.stackRegSet = _G.sendSet;
3513       _G.sendSet = NULL;
3514     }
3515
3516     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3517
3518     // push return address
3519     // push $ on return stack, then replace with retlbl
3520
3521     /* Thanks to Thorsten Klose for pointing out that the following
3522      * snippet should be interrupt safe */
3523     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3524     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3525
3526     pic16_emitpcodeNULLop(POC_PUSH);
3527
3528     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3530     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3531     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3532     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3533     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3534
3535
3536     /* restore interrupt control register */
3537     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3538     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3539
3540     /* make the call by writing the pointer into pc */
3541     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3542     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3543
3544     // note: MOVFF to PCL not allowed
3545     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3546     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3547
3548
3549     /* return address is here: (X) */
3550     pic16_emitpLabelFORCE(retlbl->key);
3551
3552     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3553
3554     GpsuedoStkPtr=0;
3555     /* if we need assign a result value */
3556     if ((IS_ITEMP(IC_RESULT(ic))
3557           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3558               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3559         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3560
3561       _G.accInUse++;
3562       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3563       _G.accInUse--;
3564
3565       assignResultValue(IC_RESULT(ic), 1);
3566
3567       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3568               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3569                 
3570       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3571     }
3572
3573 //    stackParms -= use_wreg;
3574     
3575     if(stackParms>0) {
3576       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3577       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3578       if(STACK_MODEL_LARGE) {
3579         emitSKPNC;
3580         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3581       }
3582     }
3583 }
3584
3585 /*-----------------------------------------------------------------*/
3586 /* resultRemat - result  is rematerializable                       */
3587 /*-----------------------------------------------------------------*/
3588 static int resultRemat (iCode *ic)
3589 {
3590   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3591   if (SKIP_IC(ic) || ic->op == IFX)
3592     return 0;
3593
3594   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3595     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3596     if (sym->remat && !POINTER_SET(ic)) 
3597       return 1;
3598   }
3599
3600   return 0;
3601 }
3602
3603 #if defined(__BORLANDC__) || defined(_MSC_VER)
3604 #define STRCASECMP stricmp
3605 #else
3606 #define STRCASECMP strcasecmp
3607 #endif
3608
3609 #if 0
3610 /*-----------------------------------------------------------------*/
3611 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3612 /*-----------------------------------------------------------------*/
3613 static bool inExcludeList(char *s)
3614 {
3615   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3616     int i =0;
3617     
3618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3619     if (options.excludeRegs[i] &&
3620     STRCASECMP(options.excludeRegs[i],"none") == 0)
3621         return FALSE ;
3622
3623     for ( i = 0 ; options.excludeRegs[i]; i++) {
3624         if (options.excludeRegs[i] &&
3625         STRCASECMP(s,options.excludeRegs[i]) == 0)
3626             return TRUE;
3627     }
3628     return FALSE ;
3629 }
3630 #endif
3631
3632 /*-----------------------------------------------------------------*/
3633 /* genFunction - generated code for function entry                 */
3634 /*-----------------------------------------------------------------*/
3635 static void genFunction (iCode *ic)
3636 {
3637   symbol *sym;
3638   sym_link *ftype;
3639   
3640     FENTRY;
3641     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3642
3643     pic16_labelOffset += (max_key+4);
3644     max_key=0;
3645     GpsuedoStkPtr=0;
3646     _G.nRegsSaved = 0;
3647         
3648     ftype = operandType(IC_LEFT(ic));
3649     sym = OP_SYMBOL(IC_LEFT(ic));
3650
3651     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3652       /* create an absolute section at the interrupt vector:
3653        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3654       symbol *asym;
3655       char asymname[128];
3656       pBlock *apb;
3657
3658 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3659
3660         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3661           sprintf(asymname, "ivec_%s", sym->name);
3662         else
3663           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3664   
3665         /* when an interrupt is declared as naked, do not emit the special
3666          * wrapper segment at vector address. The user should take care for
3667          * this instead. -- VR */
3668
3669         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3670           asym = newSymbol(asymname, 0);
3671           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3672           pic16_addpBlock( apb );
3673
3674           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3675           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3676           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3677           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3678           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3679                 
3680           /* mark the end of this tiny function */
3681           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3682         } else {
3683           sprintf(asymname, "%s", sym->rname);
3684         }
3685
3686         {
3687           absSym *abSym;
3688
3689             abSym = Safe_calloc(1, sizeof(absSym));
3690             strcpy(abSym->name, asymname);
3691
3692             switch( FUNC_INTNO(sym->type) ) {
3693               case 0: abSym->address = 0x000000; break;
3694               case 1: abSym->address = 0x000008; break;
3695               case 2: abSym->address = 0x000018; break;
3696               
3697               default:
3698 //                fprintf(stderr, "no interrupt number is given\n");
3699                 abSym->address = -1; break;
3700             }
3701
3702             /* relocate interrupt vectors if needed */
3703             if(abSym->address != -1)
3704               abSym->address += pic16_options.ivt_loc;
3705
3706             addSet(&absSymSet, abSym);
3707         }
3708     }
3709
3710     /* create the function header */
3711     pic16_emitcode(";","-----------------------------------------");
3712     pic16_emitcode(";"," function %s",sym->name);
3713     pic16_emitcode(";","-----------------------------------------");
3714
3715     pic16_emitcode("","%s:",sym->rname);
3716     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3717
3718     {
3719       absSym *ab;
3720
3721         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3722           if(!strcmp(ab->name, sym->rname)) {
3723             pic16_pBlockConvert2Absolute(pb);
3724             break;
3725           }
3726         }
3727     }
3728
3729     if(IFFUNC_ISNAKED(ftype)) {
3730       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3731       return;
3732     }
3733         
3734     /* if critical function then turn interrupts off */
3735     if (IFFUNC_ISCRITICAL(ftype)) {
3736       //pic16_emitcode("clr","ea");
3737     }
3738
3739     currFunc = sym;             /* update the currFunc symbol */
3740     _G.fregsUsed = sym->regsUsed;
3741     _G.sregsAlloc = newBitVect(128);
3742     
3743
3744     /* if this is an interrupt service routine then
3745      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3746     if (IFFUNC_ISISR(sym->type)) {
3747         _G.usefastretfie = 1;   /* use shadow registers by default */
3748         
3749         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3750         if(!FUNC_ISSHADOWREGS(sym->type)) {
3751           /* do not save WREG,STATUS,BSR for high priority interrupts
3752            * because they are stored in the hardware shadow registers already */
3753           _G.usefastretfie = 0;
3754           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3755           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3756           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3757         }
3758
3759         /* these should really be optimized somehow, because not all
3760          * interrupt handlers modify them */
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3762         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3763         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3764         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3765         
3766 //        pic16_pBlockConvert2ISR(pb);
3767     }
3768
3769     /* emit code to setup stack frame if user enabled,
3770      * and function is not main() */
3771     
3772 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3773     if(strcmp(sym->name, "main")) {
3774       if(0 
3775         || !options.ommitFramePtr 
3776 //        || sym->regsUsed
3777         || IFFUNC_ARGS(sym->type)
3778         || FUNC_HASSTACKPARM(sym->etype)
3779         ) {
3780         /* setup the stack frame */
3781         if(STACK_MODEL_LARGE)
3782           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3783         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3784
3785         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3786         if(STACK_MODEL_LARGE)
3787           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3788       }
3789     }
3790
3791     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3792           && sym->stack) {
3793
3794       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3795
3796       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3797       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3798       emitSKPC;
3799       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3800     }
3801           
3802     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3803       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3804         _G.useWreg = 0;
3805       else
3806         _G.useWreg = 1;
3807     } else
3808       _G.useWreg = 0;
3809
3810     /* if callee-save to be used for this function
3811      * then save the registers being used in this function */
3812 //    if (IFFUNC_CALLEESAVES(sym->type))
3813     {
3814       int i;
3815
3816         /* if any registers used */
3817         if (sym->regsUsed) {
3818           /* save the registers used */
3819           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3820           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3821           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3822             if (bitVectBitValue(sym->regsUsed,i)) {
3823               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3824               _G.nRegsSaved++;
3825
3826               if(!pic16_regWithIdx(i)->wasUsed) {
3827                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3828                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3829                 pic16_regWithIdx(i)->wasUsed = 1;
3830               }
3831             }
3832           }
3833           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3834         }
3835     }
3836         
3837     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3838 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3839 }
3840
3841 /*-----------------------------------------------------------------*/
3842 /* genEndFunction - generates epilogue for functions               */
3843 /*-----------------------------------------------------------------*/
3844 static void genEndFunction (iCode *ic)
3845 {
3846   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3847
3848     FENTRY;
3849
3850     if(IFFUNC_ISNAKED(sym->type)) {
3851       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3852       return;
3853     }
3854
3855     _G.stack_lat = 0;
3856
3857     /* add code for ISCRITICAL */
3858     if(IFFUNC_ISCRITICAL(sym->type)) {
3859       /* if critical function, turn on interrupts */
3860       
3861       /* TODO: add code here -- VR */
3862     }
3863     
3864 //    sym->regsUsed = _G.fregsUsed;
3865     
3866     /* now we need to restore the registers */
3867     /* if any registers used */
3868
3869     /* first restore registers that might be used for stack access */
3870     if(_G.sregsAllocSet) {
3871     regs *sr;
3872     
3873       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3874       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3875         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3876       }
3877     }
3878
3879     if (sym->regsUsed) {
3880       int i;
3881
3882         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3883         /* restore registers used */
3884         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3885         for ( i = sym->regsUsed->size; i >= 0; i--) {
3886           if (bitVectBitValue(sym->regsUsed,i)) {
3887             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3888             _G.nRegsSaved--;
3889           }
3890         }
3891         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3892     }
3893
3894       
3895
3896     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3897           && sym->stack) {
3898       if (sym->stack == 1) {
3899         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3900         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3901       } else {
3902         // we have to add more than one...
3903         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3904         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3905         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3906         emitSKPNC;
3907         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3908         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3909         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3910       }
3911     }
3912
3913     if(strcmp(sym->name, "main")) {
3914       if(0
3915         || !options.ommitFramePtr
3916 //        || sym->regsUsed
3917         || IFFUNC_ARGS(sym->type)
3918         || FUNC_HASSTACKPARM(sym->etype)
3919         ) {
3920         /* restore stack frame */
3921         if(STACK_MODEL_LARGE)
3922           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3923         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3924       }
3925     }
3926
3927     _G.useWreg = 0;
3928
3929     if (IFFUNC_ISISR(sym->type)) {
3930       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3931       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3932       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3933       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3934
3935       if(!FUNC_ISSHADOWREGS(sym->type)) {
3936         /* do not restore interrupt vector for WREG,STATUS,BSR
3937          * for high priority interrupt, see genFunction */
3938         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3939         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3940         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3941       }
3942 //      _G.interruptvector = 0;         /* sanity check */
3943
3944
3945       /* if debug then send end of function */
3946 /*      if (options.debug && currFunc)  */
3947       if (currFunc) {
3948         debugFile->writeEndFunction (currFunc, ic, 1);
3949       }
3950         
3951       if(_G.usefastretfie)
3952         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3953       else
3954         pic16_emitpcodeNULLop(POC_RETFIE);
3955
3956       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3957       
3958       _G.usefastretfie = 0;
3959       return;
3960     }
3961
3962     if (IFFUNC_ISCRITICAL(sym->type)) {
3963       pic16_emitcode("setb","ea");
3964     }
3965
3966     /* if debug then send end of function */
3967     if (currFunc) {
3968       debugFile->writeEndFunction (currFunc, ic, 1);
3969     }
3970
3971     /* insert code to restore stack frame, if user enabled it
3972      * and function is not main() */
3973          
3974
3975     pic16_emitpcodeNULLop(POC_RETURN);
3976
3977     /* Mark the end of a function */
3978     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3979 }
3980
3981
3982 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3983 {
3984   unsigned long lit=1;
3985   operand *op;
3986
3987     op = IC_LEFT(ic);
3988   
3989     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3990     if(AOP_TYPE(op) == AOP_LIT) {
3991       if(!IS_FLOAT(operandType( op ))) {
3992         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3993       } else {
3994         union {
3995           unsigned long lit_int;
3996           float lit_float;
3997         } info;
3998         
3999         /* take care if literal is a float */
4000         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4001         lit = info.lit_int;
4002       }
4003     }
4004
4005     if(is_LitOp(op)) {
4006       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4007         pic16_emitpcode(POC_CLRF, dest);
4008       } else {
4009         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4010         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4011       }
4012     } else {
4013       if(dest->type == PO_WREG && (offset == 0)) {
4014         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4015       return;
4016     }
4017     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4018   }
4019 }
4020
4021 /*-----------------------------------------------------------------*/
4022 /* genRet - generate code for return statement                     */
4023 /*-----------------------------------------------------------------*/
4024 static void genRet (iCode *ic)
4025 {
4026   int size;
4027   operand *left;
4028
4029     FENTRY;
4030         /* if we have no return value then
4031          * just generate the "ret" */
4032         
4033         if (!IC_LEFT(ic)) 
4034                 goto jumpret;       
4035     
4036         /* we have something to return then
4037          * move the return value into place */
4038         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4039         size = AOP_SIZE(IC_LEFT(ic));
4040
4041         if(size <= 4) {
4042           if(size>3)
4043             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4044           
4045           if(size>2)
4046             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4047
4048           if(size>1)
4049             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4050           
4051           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4052
4053         } else {
4054                 /* >32-bits, setup stack and FSR0 */
4055                 while (size--) {
4056 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4057 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4058
4059                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4060
4061 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4062                         GpsuedoStkPtr++;
4063                 }
4064                         
4065                 /* setup FSR0 */
4066                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4067                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4068
4069                 if(STACK_MODEL_LARGE) {
4070                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4071                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4072                 } else {
4073                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4074                 }
4075         }
4076                                 
4077 #if 0
4078         /* old code, left here for reference -- VR */    
4079         while (size--) {
4080           char *l ;
4081
4082                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4083                         /* #NOCHANGE */
4084                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4085                         pic16_emitpcomment("push %s",l);
4086                         pushed++;
4087                 } else {
4088                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4089                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4090                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4091                         
4092                         if (strcmp(fReturn[offset],l)) {
4093                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4094                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4095                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4096                                 } else {
4097                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4098                                 }
4099                                 
4100                                 if(size) {
4101                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4102                                 }
4103                                 offset++;
4104                         }
4105                 }
4106         }    
4107
4108         if (pushed) {
4109                 while(pushed) {
4110                         pushed--;
4111                         if (strcmp(fReturn[pushed],"a"))
4112                                 pic16_emitcode("pop",fReturn[pushed]);
4113                         else
4114                                 pic16_emitcode("pop","acc");
4115                 }
4116         }
4117 #endif
4118
4119
4120         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4121     
4122 jumpret:
4123         /* generate a jump to the return label
4124          * if the next is not the return statement */
4125         if (!(ic->next && ic->next->op == LABEL
4126                 && IC_LABEL(ic->next) == returnLabel)) {
4127         
4128                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4129                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4130         }
4131 }
4132
4133 /*-----------------------------------------------------------------*/
4134 /* genLabel - generates a label                                    */
4135 /*-----------------------------------------------------------------*/
4136 static void genLabel (iCode *ic)
4137 {
4138   FENTRY;
4139
4140   /* special case never generate */
4141   if (IC_LABEL(ic) == entryLabel)
4142     return ;
4143
4144   pic16_emitpLabel(IC_LABEL(ic)->key);
4145 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4146 }
4147
4148 /*-----------------------------------------------------------------*/
4149 /* genGoto - generates a goto                                      */
4150 /*-----------------------------------------------------------------*/
4151 //tsd
4152 static void genGoto (iCode *ic)
4153 {
4154   FENTRY;
4155   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4156 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4157 }
4158
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genMultbits :- multiplication of bits                           */
4162 /*-----------------------------------------------------------------*/
4163 static void genMultbits (operand *left, 
4164                          operand *right, 
4165                          operand *result)
4166 {
4167   FENTRY;
4168
4169   if(!pic16_sameRegs(AOP(result),AOP(right)))
4170     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4171
4172   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4173   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4174   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4175
4176 }
4177
4178
4179 /*-----------------------------------------------------------------*/
4180 /* genMultOneByte : 8 bit multiplication & division                */
4181 /*-----------------------------------------------------------------*/
4182 static void genMultOneByte (operand *left,
4183                             operand *right,
4184                             operand *result)
4185 {
4186
4187   FENTRY;
4188   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4189   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4190
4191   /* (if two literals, the value is computed before) */
4192   /* if one literal, literal on the right */
4193   if (AOP_TYPE(left) == AOP_LIT){
4194     operand *t = right;
4195     right = left;
4196     left = t;
4197   }
4198
4199         /* size is already checked in genMult == 1 */
4200 //      size = AOP_SIZE(result);
4201
4202         if (AOP_TYPE(right) == AOP_LIT){
4203                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4204                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4205                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4206                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207         } else {
4208                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4209                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4210                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4211                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212         }
4213         
4214         pic16_genMult8X8_8 (left, right,result);
4215 }
4216
4217 /*-----------------------------------------------------------------*/
4218 /* genMultOneWord : 16 bit multiplication                          */
4219 /*-----------------------------------------------------------------*/
4220 static void genMultOneWord (operand *left,
4221                             operand *right,
4222                             operand *result)
4223 {
4224   FENTRY;
4225   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4226   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4227
4228   /* (if two literals, the value is computed before)
4229    * if one literal, literal on the right */
4230   if (AOP_TYPE(left) == AOP_LIT){
4231     operand *t = right;
4232     right = left;
4233     left = t;
4234   }
4235
4236   /* size is checked already == 2 */
4237 //  size = AOP_SIZE(result);
4238
4239   if (AOP_TYPE(right) == AOP_LIT) {
4240     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4241       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4242       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4243       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4244   } else {
4245     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4246       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4247       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4248       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4249   }
4250         
4251   pic16_genMult16X16_16(left, right,result);
4252 }
4253
4254 /*-----------------------------------------------------------------*/
4255 /* genMultOneLong : 32 bit multiplication                          */
4256 /*-----------------------------------------------------------------*/
4257 static void genMultOneLong (operand *left,
4258                             operand *right,
4259                             operand *result)
4260 {
4261   FENTRY;
4262   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4263   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4264
4265   /* (if two literals, the value is computed before)
4266    * if one literal, literal on the right */
4267   if (AOP_TYPE(left) == AOP_LIT){
4268     operand *t = right;
4269     right = left;
4270     left = t;
4271   }
4272
4273   /* size is checked already == 4 */
4274 //  size = AOP_SIZE(result);
4275
4276   if (AOP_TYPE(right) == AOP_LIT) {
4277     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4278         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4279         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4280         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4281   } else {
4282     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4283         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4284         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4285         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4286   }
4287         
4288   pic16_genMult32X32_32(left, right,result);
4289 }
4290
4291
4292
4293 /*-----------------------------------------------------------------*/
4294 /* genMult - generates code for multiplication                     */
4295 /*-----------------------------------------------------------------*/
4296 static void genMult (iCode *ic)
4297 {
4298   operand *left = IC_LEFT(ic);
4299   operand *right = IC_RIGHT(ic);
4300   operand *result= IC_RESULT(ic);   
4301
4302     FENTRY;
4303         /* assign the amsops */
4304         pic16_aopOp (left,ic,FALSE);
4305         pic16_aopOp (right,ic,FALSE);
4306         pic16_aopOp (result,ic,TRUE);
4307
4308         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4309
4310         /* special cases first *
4311         * both are bits */
4312         if (AOP_TYPE(left) == AOP_CRY
4313                 && AOP_TYPE(right)== AOP_CRY) {
4314                 genMultbits(left,right,result);
4315           goto release ;
4316         }
4317
4318         /* if both are of size == 1 */
4319         if(AOP_SIZE(left) == 1
4320                 && AOP_SIZE(right) == 1) {
4321                 genMultOneByte(left,right,result);
4322           goto release ;
4323         }
4324
4325         /* if both are of size == 2 */
4326         if(AOP_SIZE(left) == 2
4327                 && AOP_SIZE(right) == 2) {
4328                 genMultOneWord(left, right, result);
4329           goto release;
4330         }
4331         
4332         /* if both are of size == 4 */
4333         if(AOP_SIZE(left) == 4
4334                 && AOP_SIZE(right) == 4) {
4335                 genMultOneLong(left, right, result);
4336           goto release;
4337         }
4338         
4339         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4340
4341
4342         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4343         /* should have been converted to function call */
4344         assert(0) ;
4345
4346 release :
4347         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349         pic16_freeAsmop(result,NULL,ic,TRUE); 
4350 }
4351
4352 /*-----------------------------------------------------------------*/
4353 /* genDivbits :- division of bits                                  */
4354 /*-----------------------------------------------------------------*/
4355 static void genDivbits (operand *left, 
4356                         operand *right, 
4357                         operand *result)
4358 {
4359   char *l;
4360
4361     FENTRY;
4362     /* the result must be bit */    
4363     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4364     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4365
4366     MOVA(l);    
4367
4368     pic16_emitcode("div","ab");
4369     pic16_emitcode("rrc","a");
4370     pic16_aopPut(AOP(result),"c",0);
4371 }
4372
4373 /*-----------------------------------------------------------------*/
4374 /* genDivOneByte : 8 bit division                                  */
4375 /*-----------------------------------------------------------------*/
4376 static void genDivOneByte (operand *left,
4377                            operand *right,
4378                            operand *result)
4379 {
4380   sym_link *opetype = operandType(result);
4381   char *l ;
4382   symbol *lbl ;
4383   int size,offset;
4384
4385         /* result = divident / divisor
4386          * - divident may be a register or a literal,
4387          * - divisor may be a register or a literal,
4388          * so there are 3 cases (literal / literal is optimized
4389          * by the front-end) to handle.
4390          * In addition we must handle signed and unsigned, which
4391          * result in 6 final different cases -- VR */
4392
4393     FENTRY;
4394     
4395     size = AOP_SIZE(result) - 1;
4396     offset = 1;
4397     /* signed or unsigned */
4398     if (SPEC_USIGN(opetype)) {
4399       pCodeOp *pct1,    /* count */
4400                 *pct2,  /* reste */
4401                 *pct3;  /* temp */
4402       symbol *label1, *label2, *label3;;
4403
4404
4405         /* unsigned is easy */
4406
4407         pct1 = pic16_popGetTempReg(1);
4408         pct2 = pic16_popGetTempReg(1);
4409         pct3 = pic16_popGetTempReg(1);
4410         
4411         label1 = newiTempLabel(NULL);
4412         label2 = newiTempLabel(NULL);
4413         label3 = newiTempLabel(NULL);
4414
4415         /* the following algorithm is extracted from divuint.c */
4416
4417         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4418         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4419         
4420         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4421
4422         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4423         
4424         pic16_emitpLabel(label1->key);
4425         
4426         emitCLRC;
4427         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4428
4429
4430         emitCLRC;
4431         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4432         
4433
4434         emitSKPNC;
4435         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4436         
4437         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4438         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4439         
4440         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4441         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4442         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4443         
4444         pic16_emitpLabel( label3->key );
4445         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4446         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4447         
4448         
4449
4450         pic16_emitpLabel(label2->key);
4451         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4452         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4453         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4454         
4455         /* result is in wreg */
4456         if(AOP_TYPE(result) != AOP_ACC)
4457                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4458
4459         pic16_popReleaseTempReg( pct3, 1);
4460         pic16_popReleaseTempReg( pct2, 1);
4461         pic16_popReleaseTempReg( pct1, 1);
4462
4463         return ;
4464     }
4465
4466     /* signed is a little bit more difficult */
4467
4468     /* save the signs of the operands */
4469     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4470     MOVA(l);    
4471     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4472     pic16_emitcode("push","acc"); /* save it on the stack */
4473
4474     /* now sign adjust for both left & right */
4475     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4476     MOVA(l);       
4477     lbl = newiTempLabel(NULL);
4478     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4479     pic16_emitcode("cpl","a");   
4480     pic16_emitcode("inc","a");
4481     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4482     pic16_emitcode("mov","b,a");
4483
4484     /* sign adjust left side */
4485     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4486     MOVA(l);
4487
4488     lbl = newiTempLabel(NULL);
4489     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4490     pic16_emitcode("cpl","a");
4491     pic16_emitcode("inc","a");
4492     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4493
4494     /* now the division */
4495     pic16_emitcode("div","ab");
4496     /* we are interested in the lower order
4497     only */
4498     pic16_emitcode("mov","b,a");
4499     lbl = newiTempLabel(NULL);
4500     pic16_emitcode("pop","acc");   
4501     /* if there was an over flow we don't 
4502     adjust the sign of the result */
4503     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4504     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4505     CLRC;
4506     pic16_emitcode("clr","a");
4507     pic16_emitcode("subb","a,b");
4508     pic16_emitcode("mov","b,a");
4509     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4510
4511     /* now we are done */
4512     pic16_aopPut(AOP(result),"b",0);
4513     if(size > 0){
4514         pic16_emitcode("mov","c,b.7");
4515         pic16_emitcode("subb","a,acc");   
4516     }
4517     while (size--)
4518         pic16_aopPut(AOP(result),"a",offset++);
4519
4520 }
4521
4522 /*-----------------------------------------------------------------*/
4523 /* genDiv - generates code for division                            */
4524 /*-----------------------------------------------------------------*/
4525 static void genDiv (iCode *ic)
4526 {
4527     operand *left = IC_LEFT(ic);
4528     operand *right = IC_RIGHT(ic);
4529     operand *result= IC_RESULT(ic);   
4530
4531
4532         /* Division is a very lengthy algorithm, so it is better
4533          * to call support routines than inlining algorithm.
4534          * Division functions written here just in case someone
4535          * wants to inline and not use the support libraries -- VR */
4536
4537     FENTRY;
4538     
4539     /* assign the amsops */
4540     pic16_aopOp (left,ic,FALSE);
4541     pic16_aopOp (right,ic,FALSE);
4542     pic16_aopOp (result,ic,TRUE);
4543
4544     /* special cases first */
4545     /* both are bits */
4546     if (AOP_TYPE(left) == AOP_CRY &&
4547         AOP_TYPE(right)== AOP_CRY) {
4548         genDivbits(left,right,result);
4549         goto release ;
4550     }
4551
4552     /* if both are of size == 1 */
4553     if (AOP_SIZE(left) == 1 &&
4554         AOP_SIZE(right) == 1 ) {
4555         genDivOneByte(left,right,result);
4556         goto release ;
4557     }
4558
4559     /* should have been converted to function call */
4560     assert(0);
4561 release :
4562     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4563     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4564     pic16_freeAsmop(result,NULL,ic,TRUE); 
4565 }
4566
4567 /*-----------------------------------------------------------------*/
4568 /* genModbits :- modulus of bits                                   */
4569 /*-----------------------------------------------------------------*/
4570 static void genModbits (operand *left, 
4571                         operand *right, 
4572                         operand *result)
4573 {
4574   char *l;
4575
4576     FENTRY;  
4577     
4578     werror(W_POSSBUG2, __FILE__, __LINE__);
4579     /* the result must be bit */    
4580     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4581     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4582
4583     MOVA(l);       
4584
4585     pic16_emitcode("div","ab");
4586     pic16_emitcode("mov","a,b");
4587     pic16_emitcode("rrc","a");
4588     pic16_aopPut(AOP(result),"c",0);
4589 }
4590
4591 /*-----------------------------------------------------------------*/
4592 /* genModOneByte : 8 bit modulus                                   */
4593 /*-----------------------------------------------------------------*/
4594 static void genModOneByte (operand *left,
4595                            operand *right,
4596                            operand *result)
4597 {
4598   sym_link *opetype = operandType(result);
4599   char *l ;
4600   symbol *lbl ;
4601
4602     FENTRY;
4603     werror(W_POSSBUG2, __FILE__, __LINE__);
4604
4605     /* signed or unsigned */
4606     if (SPEC_USIGN(opetype)) {
4607         /* unsigned is easy */
4608         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4609         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4610         MOVA(l);    
4611         pic16_emitcode("div","ab");
4612         pic16_aopPut(AOP(result),"b",0);
4613         return ;
4614     }
4615
4616     /* signed is a little bit more difficult */
4617
4618     /* save the signs of the operands */
4619     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4620     MOVA(l);
4621
4622     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4623     pic16_emitcode("push","acc"); /* save it on the stack */
4624
4625     /* now sign adjust for both left & right */
4626     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4627     MOVA(l);
4628
4629     lbl = newiTempLabel(NULL);
4630     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4631     pic16_emitcode("cpl","a");   
4632     pic16_emitcode("inc","a");
4633     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4634     pic16_emitcode("mov","b,a"); 
4635
4636     /* sign adjust left side */
4637     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4638     MOVA(l);
4639
4640     lbl = newiTempLabel(NULL);
4641     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4642     pic16_emitcode("cpl","a");   
4643     pic16_emitcode("inc","a");
4644     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4645
4646     /* now the multiplication */
4647     pic16_emitcode("div","ab");
4648     /* we are interested in the lower order
4649     only */
4650     lbl = newiTempLabel(NULL);
4651     pic16_emitcode("pop","acc");   
4652     /* if there was an over flow we don't 
4653     adjust the sign of the result */
4654     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4655     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4656     CLRC ;
4657     pic16_emitcode("clr","a");
4658     pic16_emitcode("subb","a,b");
4659     pic16_emitcode("mov","b,a");
4660     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4661
4662     /* now we are done */
4663     pic16_aopPut(AOP(result),"b",0);
4664
4665 }
4666
4667 /*-----------------------------------------------------------------*/
4668 /* genMod - generates code for division                            */
4669 /*-----------------------------------------------------------------*/
4670 static void genMod (iCode *ic)
4671 {
4672   operand *left = IC_LEFT(ic);
4673   operand *right = IC_RIGHT(ic);
4674   operand *result= IC_RESULT(ic);  
4675
4676     FENTRY;
4677     
4678     /* assign the amsops */
4679     pic16_aopOp (left,ic,FALSE);
4680     pic16_aopOp (right,ic,FALSE);
4681     pic16_aopOp (result,ic,TRUE);
4682
4683     /* special cases first */
4684     /* both are bits */
4685     if (AOP_TYPE(left) == AOP_CRY &&
4686         AOP_TYPE(right)== AOP_CRY) {
4687         genModbits(left,right,result);
4688         goto release ;
4689     }
4690
4691     /* if both are of size == 1 */
4692     if (AOP_SIZE(left) == 1 &&
4693         AOP_SIZE(right) == 1 ) {
4694         genModOneByte(left,right,result);
4695         goto release ;
4696     }
4697
4698     /* should have been converted to function call */
4699     assert(0);
4700
4701 release :
4702     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4703     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4704     pic16_freeAsmop(result,NULL,ic,TRUE); 
4705 }
4706
4707 /*-----------------------------------------------------------------*/
4708 /* genIfxJump :- will create a jump depending on the ifx           */
4709 /*-----------------------------------------------------------------*/
4710 /*
4711   note: May need to add parameter to indicate when a variable is in bit space.
4712 */
4713 static void genIfxJump (iCode *ic, char *jval)
4714 {
4715   FENTRY;
4716   
4717     /* if true label then we jump if condition
4718     supplied is true */
4719     if ( IC_TRUE(ic) ) {
4720
4721         if(strcmp(jval,"a") == 0)
4722           emitSKPZ;
4723         else if (strcmp(jval,"c") == 0)
4724           emitSKPNC;
4725         else {
4726           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4727           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4728         }
4729
4730         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4731         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4732
4733     }
4734     else {
4735         /* false label is present */
4736         if(strcmp(jval,"a") == 0)
4737           emitSKPNZ;
4738         else if (strcmp(jval,"c") == 0)
4739           emitSKPC;
4740         else {
4741           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4742           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4743         }
4744
4745         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4746         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4747
4748     }
4749
4750
4751     /* mark the icode as generated */
4752     ic->generated = 1;
4753 }
4754
4755 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4756 {
4757   FENTRY;
4758   
4759     /* if true label then we jump if condition
4760     supplied is true */
4761     if ( IC_TRUE(ic) ) {
4762       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4763       pic16_emitpcode(POC_BTFSC, jop);
4764
4765       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4766       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4767
4768     } else {
4769       /* false label is present */
4770       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4771       pic16_emitpcode(POC_BTFSS, jop);
4772           
4773       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4774       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4775     }
4776
4777
4778     /* mark the icode as generated */
4779     ic->generated = 1;
4780 }
4781
4782 #if 0
4783 // not needed ATM
4784
4785 /*-----------------------------------------------------------------*/
4786 /* genSkip                                                         */
4787 /*-----------------------------------------------------------------*/
4788 static void genSkip(iCode *ifx,int status_bit)
4789 {
4790   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4791   if(!ifx)
4792     return;
4793
4794   if ( IC_TRUE(ifx) ) {
4795     switch(status_bit) {
4796     case 'z':
4797       emitSKPNZ;
4798       break;
4799
4800     case 'c':
4801       emitSKPNC;
4802       break;
4803
4804     case 'd':
4805       emitSKPDC;
4806       break;
4807
4808     }
4809
4810     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4811     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4812
4813   } else {
4814
4815     switch(status_bit) {
4816
4817     case 'z':
4818       emitSKPZ;
4819       break;
4820
4821     case 'c':
4822       emitSKPC;
4823       break;
4824
4825     case 'd':
4826       emitSKPDC;
4827       break;
4828     }
4829     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4830     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4831
4832   }
4833
4834 }
4835 #endif
4836
4837 /*-----------------------------------------------------------------*/
4838 /* genSkipc                                                        */
4839 /*-----------------------------------------------------------------*/
4840 static void genSkipc(resolvedIfx *rifx)
4841 {
4842   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4843   
4844   if(!rifx)
4845     return;
4846
4847   if(rifx->condition)
4848     emitSKPNC;
4849   else
4850     emitSKPC;
4851
4852   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4853   rifx->generated = 1;
4854 }
4855
4856 #if !(USE_SIMPLE_GENCMP)
4857 /*-----------------------------------------------------------------*/
4858 /* genSkipz2                                                       */
4859 /*-----------------------------------------------------------------*/
4860 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4861 {
4862   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4863   
4864   if(!rifx)
4865     return;
4866
4867   if( (rifx->condition ^ invert_condition) & 1)
4868     emitSKPZ;
4869   else
4870     emitSKPNZ;
4871
4872   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4873   rifx->generated = 1;
4874 }
4875 #endif
4876
4877 #if 0
4878 /*-----------------------------------------------------------------*/
4879 /* genSkipz                                                        */
4880 /*-----------------------------------------------------------------*/
4881 static void genSkipz(iCode *ifx, int condition)
4882 {
4883   if(!ifx)
4884     return;
4885
4886   if(condition)
4887     emitSKPNZ;
4888   else
4889     emitSKPZ;
4890
4891   if ( IC_TRUE(ifx) )
4892     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4893   else
4894     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4895
4896   if ( IC_TRUE(ifx) )
4897     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4898   else
4899     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4900
4901 }
4902 #endif
4903
4904 #if !(USE_SIMPLE_GENCMP)
4905 /*-----------------------------------------------------------------*/
4906 /* genSkipCond                                                     */
4907 /*-----------------------------------------------------------------*/
4908 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4909 {
4910   if(!rifx)
4911     return;
4912
4913   if(rifx->condition)
4914     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4915   else
4916     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4917
4918
4919   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4920   rifx->generated = 1;
4921 }
4922 #endif
4923
4924 #if 0
4925 /*-----------------------------------------------------------------*/
4926 /* genChkZeroes :- greater or less than comparison                 */
4927 /*     For each byte in a literal that is zero, inclusive or the   */
4928 /*     the corresponding byte in the operand with W                */
4929 /*     returns true if any of the bytes are zero                   */
4930 /*-----------------------------------------------------------------*/
4931 static int genChkZeroes(operand *op, int lit,  int size)
4932 {
4933
4934   int i;
4935   int flag =1;
4936
4937   while(size--) {
4938     i = (lit >> (size*8)) & 0xff;
4939
4940     if(i==0) {
4941       if(flag) 
4942         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4943       else
4944         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4945       flag = 0;
4946     }
4947   }
4948
4949   return (flag==0);
4950 }
4951 #endif
4952
4953
4954 /*-----------------------------------------------------------------*/
4955 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4956 /*                  aop (if it's NOT a literal) or from lit (if    */
4957 /*                  aop is a literal)                              */
4958 /*-----------------------------------------------------------------*/
4959 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4960   if (aop->type == AOP_LIT) {
4961     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4962   } else {
4963     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4964   }
4965 }
4966
4967 /*-----------------------------------------------------------------*/
4968 /* genCmp :- greater or less than comparison                       */
4969 /*-----------------------------------------------------------------*/
4970
4971 #if USE_SIMPLE_GENCMP           /* { */
4972
4973 /* genCmp performs a left < right comparison, stores
4974  * the outcome in result (if != NULL) and generates
4975  * control flow code for the ifx (if != NULL).
4976  *
4977  * This version leaves in sequences like
4978  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4979  * which should be optmized by the peephole
4980  * optimizer - RN 2005-01-01 */
4981 static void genCmp (operand *left,operand *right,
4982                     operand *result, iCode *ifx, int sign)
4983 {
4984   resolvedIfx rIfx;
4985   int size;
4986   int offs;
4987   symbol *templbl;
4988   operand *dummy;
4989   unsigned long lit;
4990   unsigned long mask;
4991   int performedLt;
4992
4993   FENTRY;
4994   
4995   assert (AOP_SIZE(left) == AOP_SIZE(right));
4996   assert (left && right);
4997
4998   size = AOP_SIZE(right) - 1;
4999   mask = (0x100UL << (size*8)) - 1;
5000   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5001   performedLt = 1;
5002   templbl = NULL;
5003   lit = 0;
5004   
5005   resolveIfx (&rIfx, ifx);
5006
5007   /* handle for special cases */
5008   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5009       return;
5010
5011   /**********************************************************************
5012    * handle bits - bit compares are promoted to int compares seemingly! *
5013    **********************************************************************/
5014 #if 0
5015   // THIS IS COMPLETELY UNTESTED!
5016   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5017     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5018     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5019     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5020
5021     emitSETC;
5022     // 1 < {0,1} is false --> clear C by skipping the next instruction
5023     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5024     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5025     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5026     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5027     emitCLRC; // only skipped for left=0 && right=1
5028
5029     goto correct_result_in_carry;
5030   } // if
5031 #endif
5032
5033   /*************************************************
5034    * make sure that left is register (or the like) *
5035    *************************************************/
5036   if (!isAOP_REGlike(left)) {
5037     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5038     assert (isAOP_LIT(left));
5039     assert (isAOP_REGlike(right));
5040     // swap left and right
5041     // left < right <==> right > left <==> (right >= left + 1)
5042     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5043
5044     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5045       // MAXVALUE < right? always false
5046       if (performedLt) emitCLRC; else emitSETC;
5047       goto correct_result_in_carry;
5048     } // if
5049
5050     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5051     // that's why we handled it above.
5052     lit++;
5053
5054     dummy = left;
5055     left = right;
5056     right = dummy;
5057
5058     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5059   } else if (isAOP_LIT(right)) {
5060     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5061   } // if
5062
5063   assert (isAOP_REGlike(left)); // left must be register or the like
5064   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5065
5066   /*************************************************
5067    * special cases go here                         *
5068    *************************************************/
5069
5070   if (isAOP_LIT(right)) {
5071     if (!sign) {
5072       // unsigned comparison to a literal
5073       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5074       if (lit == 0) {
5075         // unsigned left < 0? always false
5076         if (performedLt) emitCLRC; else emitSETC;
5077         goto correct_result_in_carry;
5078       }
5079     } else {
5080       // signed comparison to a literal
5081       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5082       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5083         // signed left < 0x80000000? always false
5084         if (performedLt) emitCLRC; else emitSETC;
5085         goto correct_result_in_carry;
5086       } else if (lit == 0) {
5087         // compare left < 0; set CARRY if SIGNBIT(left) is set
5088         if (performedLt) emitSETC; else emitCLRC;
5089         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5090         if (performedLt) emitCLRC; else emitSETC;
5091         goto correct_result_in_carry;
5092       }
5093     } // if (!sign)
5094   } // right is literal
5095
5096   /*************************************************
5097    * perform a general case comparison             *
5098    * make sure we get CARRY==1 <==> left >= right  *
5099    *************************************************/
5100   // compare most significant bytes
5101   //DEBUGpc ("comparing bytes at offset %d", size);
5102   if (!sign) {
5103     // unsigned comparison
5104     mov2w_regOrLit (AOP(right), lit, size);
5105     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5106   } else {
5107     // signed comparison
5108     // (add 2^n to both operands then perform an unsigned comparison)
5109     if (isAOP_LIT(right)) {
5110       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5111       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5112
5113       if (litbyte == 0x80) {
5114         // left >= 0x80 -- always true, but more bytes to come
5115         pic16_mov2w (AOP(left), size);
5116         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5117         emitSETC;
5118       } else {
5119         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5120         pic16_mov2w (AOP(left), size);
5121         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5122         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5123       } // if
5124     } else {
5125       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5126       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5127       pic16_mov2w (AOP(left), size);
5128       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5129       pic16_emitpcode (POC_MOVWF, pctemp);
5130       pic16_mov2w (AOP(right), size);
5131       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5132       pic16_emitpcode (POC_SUBFW, pctemp);
5133       //pic16_popReleaseTempReg(pctemp, 1);
5134     }
5135   } // if (!sign)
5136
5137   // compare remaining bytes (treat as unsigned case from above)
5138   templbl = newiTempLabel ( NULL );
5139   offs = size;
5140   while (offs--) {
5141     //DEBUGpc ("comparing bytes at offset %d", offs);
5142     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5143     mov2w_regOrLit (AOP(right), lit, offs);
5144     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5145   } // while (offs)
5146   pic16_emitpLabel (templbl->key);
5147   goto result_in_carry;
5148
5149 result_in_carry:
5150   
5151   /****************************************************
5152    * now CARRY contains the result of the comparison: *
5153    * SUBWF sets CARRY iff                             *
5154    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5155    * (F=left, W=right)                                *
5156    ****************************************************/
5157
5158   if (performedLt) {
5159     if (result && AOP_TYPE(result) != AOP_CRY) {
5160       // value will be stored
5161       emitTOGC;
5162     } else {
5163       // value wil only be used in the following genSkipc()
5164       rIfx.condition ^= 1;
5165     }
5166   } // if
5167
5168 correct_result_in_carry:
5169
5170   // assign result to variable (if neccessary)
5171   if (result && AOP_TYPE(result) != AOP_CRY) {
5172     //DEBUGpc ("assign result");
5173     size = AOP_SIZE(result);
5174     while (size--) {
5175       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5176     } // while
5177     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5178   } // if (result)
5179
5180   // perform conditional jump
5181   if (ifx) {
5182     //DEBUGpc ("generate control flow");
5183     genSkipc (&rIfx);
5184     ifx->generated = 1;
5185   } // if
5186 }
5187
5188 #elif 1         /* } */
5189                 /* { */
5190       /* original code */
5191 static void genCmp (operand *left,operand *right,
5192                     operand *result, iCode *ifx, int sign)
5193 {
5194   int size; //, offset = 0 ;
5195   unsigned long lit = 0L,i = 0;
5196   resolvedIfx rFalseIfx;
5197   //  resolvedIfx rTrueIfx;
5198   symbol *truelbl;
5199   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5200 /*
5201   if(ifx) {
5202     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5203     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5204   }
5205 */
5206
5207   FENTRY;
5208   
5209   resolveIfx(&rFalseIfx,ifx);
5210   truelbl  = newiTempLabel(NULL);
5211   size = max(AOP_SIZE(left),AOP_SIZE(right));
5212
5213   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5214
5215 #define _swapp
5216
5217   /* if literal is on the right then swap with left */
5218   if ((AOP_TYPE(right) == AOP_LIT)) {
5219     operand *tmp = right ;
5220     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5221     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5222 #ifdef _swapp
5223
5224     lit = (lit - 1) & mask;
5225     right = left;
5226     left = tmp;
5227     rFalseIfx.condition ^= 1;
5228 #endif
5229
5230   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5231     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5232   }
5233
5234
5235   //if(IC_TRUE(ifx) == NULL)
5236   /* if left & right are bit variables */
5237   if (AOP_TYPE(left) == AOP_CRY &&
5238       AOP_TYPE(right) == AOP_CRY ) {
5239     assert (0 && "bit variables used in genCmp");
5240     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5241     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5242   } else {
5243     /* subtract right from left if at the
5244        end the carry flag is set then we know that
5245        left is greater than right */
5246
5247     symbol *lbl  = newiTempLabel(NULL);
5248
5249 #if 0
5250         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5251                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5252 #endif
5253
5254 #ifndef _swapp
5255     if(AOP_TYPE(right) == AOP_LIT) {
5256
5257       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5258
5259       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5260
5261       /* special cases */
5262
5263       if(lit == 0) {
5264
5265         if(sign != 0) 
5266           genSkipCond(&rFalseIfx,left,size-1,7);
5267         else 
5268           /* no need to compare to 0...*/
5269           /* NOTE: this is a de-generate compare that most certainly 
5270            *       creates some dead code. */
5271           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5272
5273         if(ifx) ifx->generated = 1;
5274         return;
5275
5276       }
5277       size--;
5278
5279       if(size == 0) {
5280         //i = (lit >> (size*8)) & 0xff;
5281         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5282         
5283         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5284
5285         i = ((0-lit) & 0xff);
5286         if(sign) {
5287           if( i == 0x81) { 
5288             /* lit is 0x7f, all signed chars are less than
5289              * this except for 0x7f itself */
5290             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5291             genSkipz2(&rFalseIfx,0);
5292           } else {
5293             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5294             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5295             genSkipc(&rFalseIfx);
5296           }
5297
5298         } else {
5299           if(lit == 1) {
5300             genSkipz2(&rFalseIfx,1);
5301           } else {
5302             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5303             genSkipc(&rFalseIfx);
5304           }
5305         }
5306
5307         if(ifx) ifx->generated = 1;
5308         return;
5309       }
5310
5311       /* chars are out of the way. now do ints and longs */
5312
5313
5314       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5315         
5316       /* special cases */
5317
5318       if(sign) {
5319
5320         if(lit == 0) {
5321           genSkipCond(&rFalseIfx,left,size,7);
5322           if(ifx) ifx->generated = 1;
5323           return;
5324         }
5325
5326         if(lit <0x100) {
5327           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5328
5329           //rFalseIfx.condition ^= 1;
5330           //genSkipCond(&rFalseIfx,left,size,7);
5331           //rFalseIfx.condition ^= 1;
5332
5333           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5334           if(rFalseIfx.condition)
5335             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5336           else
5337             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5338
5339           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5340           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5341           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5342
5343           while(size > 1)
5344             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5345
5346           if(rFalseIfx.condition) {
5347             emitSKPZ;
5348             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5349
5350           } else {
5351             emitSKPNZ;
5352           }
5353
5354           genSkipc(&rFalseIfx);
5355           pic16_emitpLabel(truelbl->key);
5356           if(ifx) ifx->generated = 1;
5357           return;
5358
5359         }
5360
5361         if(size == 1) {
5362
5363           if( (lit & 0xff) == 0) {
5364             /* lower byte is zero */
5365             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5366             i = ((lit >> 8) & 0xff) ^0x80;
5367             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5368             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5369             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5370             genSkipc(&rFalseIfx);
5371
5372
5373             if(ifx) ifx->generated = 1;
5374             return;
5375
5376           }
5377         } else {
5378           /* Special cases for signed longs */
5379           if( (lit & 0xffffff) == 0) {
5380             /* lower byte is zero */
5381             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5382             i = ((lit >> 8*3) & 0xff) ^0x80;
5383             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5384             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5385             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5386             genSkipc(&rFalseIfx);
5387
5388
5389             if(ifx) ifx->generated = 1;
5390             return;
5391
5392           }
5393
5394         }
5395
5396
5397         if(lit & (0x80 << (size*8))) {
5398           /* lit is negative */
5399           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5400
5401           //genSkipCond(&rFalseIfx,left,size,7);
5402
5403           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5404
5405           if(rFalseIfx.condition)
5406             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5407           else
5408             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5409
5410
5411         } else {
5412           /* lit is positive */
5413           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5414           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5415           if(rFalseIfx.condition)
5416             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5417           else
5418             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5419
5420         }
5421
5422         /*
5423           This works, but is only good for ints.
5424           It also requires a "known zero" register.
5425           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5426           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5427           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5428           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5429           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5430           genSkipc(&rFalseIfx);
5431
5432           pic16_emitpLabel(truelbl->key);
5433           if(ifx) ifx->generated = 1;
5434           return;
5435         **/
5436           
5437         /* There are no more special cases, so perform a general compare */
5438   
5439         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5440         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5441
5442         while(size--) {
5443
5444           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5445           emitSKPNZ;
5446           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447         }
5448         //rFalseIfx.condition ^= 1;
5449         genSkipc(&rFalseIfx);
5450
5451         pic16_emitpLabel(truelbl->key);
5452
5453         if(ifx) ifx->generated = 1;
5454         return;
5455
5456
5457       }
5458
5459
5460       /* sign is out of the way. So now do an unsigned compare */
5461       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5462
5463
5464       /* General case - compare to an unsigned literal on the right.*/
5465
5466       i = (lit >> (size*8)) & 0xff;
5467       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5468       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5469       while(size--) {
5470         i = (lit >> (size*8)) & 0xff;
5471
5472         if(i) {
5473           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474           emitSKPNZ;
5475           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5476         } else {
5477           /* this byte of the lit is zero, 
5478            *if it's not the last then OR in the variable */
5479           if(size)
5480             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5481         }
5482       }
5483
5484
5485       pic16_emitpLabel(lbl->key);
5486 //      pic16_emitpLabel(truelbl->key);
5487       //if(emitFinalCheck)
5488       genSkipc(&rFalseIfx);
5489       if(sign)
5490         pic16_emitpLabel(truelbl->key);
5491
5492       if(ifx) ifx->generated = 1;
5493       return;
5494
5495
5496     }
5497 #endif  // _swapp
5498
5499     if(AOP_TYPE(left) == AOP_LIT) {
5500       //symbol *lbl = newiTempLabel(NULL);
5501
5502       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5503
5504
5505       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5506
5507       /* Special cases */
5508       if((lit == 0) && (sign == 0)){
5509
5510         size--;
5511         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5512         while(size) 
5513           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5514
5515         genSkipz2(&rFalseIfx,0);
5516         if(ifx) ifx->generated = 1;
5517         return;
5518       }
5519
5520       if(size==1) {
5521         /* Special cases */
5522         lit &= 0xff;
5523         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5524           /* degenerate compare can never be true */
5525           if(rFalseIfx.condition == 0)
5526             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5527
5528           if(ifx) ifx->generated = 1;
5529           return;
5530         }
5531
5532         if(sign) {
5533           /* signed comparisons to a literal byte */
5534
5535           int lp1 = (lit+1) & 0xff;
5536
5537           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5538           switch (lp1) {
5539           case 0:
5540             rFalseIfx.condition ^= 1;
5541             genSkipCond(&rFalseIfx,right,0,7);
5542             break;
5543           case 0x7f:
5544             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5545             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5546             genSkipz2(&rFalseIfx,1);
5547             break;
5548           default:
5549             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5550             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5551             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5552             rFalseIfx.condition ^= 1;
5553             genSkipc(&rFalseIfx);
5554             break;
5555           }
5556         } else {
5557           /* unsigned comparisons to a literal byte */
5558
5559           switch(lit & 0xff ) {
5560           case 0:
5561             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5562             genSkipz2(&rFalseIfx,0);
5563             break;
5564           case 0x7f:
5565             rFalseIfx.condition ^= 1;
5566             genSkipCond(&rFalseIfx,right,0,7);
5567             break;
5568
5569           default:
5570             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5571             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5572             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5573             rFalseIfx.condition ^= 1;
5574             if (AOP_TYPE(result) == AOP_CRY)
5575               genSkipc(&rFalseIfx);
5576             else {
5577               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5578               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5579             }         
5580             break;
5581           }
5582         }
5583
5584         if(ifx) ifx->generated = 1;
5585         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5586                 goto check_carry;
5587         return;
5588
5589       } else {
5590
5591         /* Size is greater than 1 */
5592
5593         if(sign) {
5594           int lp1 = lit+1;
5595
5596           size--;
5597
5598           if(lp1 == 0) {
5599             /* this means lit = 0xffffffff, or -1 */
5600
5601
5602             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5603             rFalseIfx.condition ^= 1;
5604             genSkipCond(&rFalseIfx,right,size,7);
5605             if(ifx) ifx->generated = 1;
5606
5607             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5608               goto check_carry;
5609
5610             return;
5611           }
5612
5613           if(lit == 0) {
5614             int s = size;
5615
5616             if(rFalseIfx.condition) {
5617               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5618               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5619             }
5620
5621             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5622             while(size--)
5623               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5624
5625
5626             emitSKPZ;
5627             if(rFalseIfx.condition) {
5628               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5629               pic16_emitpLabel(truelbl->key);
5630             }else {
5631               rFalseIfx.condition ^= 1;
5632               genSkipCond(&rFalseIfx,right,s,7);
5633             }
5634
5635             if(ifx) ifx->generated = 1;
5636
5637             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5638               goto check_carry;
5639
5640             return;
5641           }
5642
5643           if((size == 1) &&  (0 == (lp1&0xff))) {
5644             /* lower byte of signed word is zero */
5645             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5646             i = ((lp1 >> 8) & 0xff) ^0x80;
5647             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5648             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5649             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5650
5651             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5652               emitTOGC;
5653               if(ifx) ifx->generated = 1;
5654               goto check_carry;
5655             } else {
5656               rFalseIfx.condition ^= 1;
5657               genSkipc(&rFalseIfx);
5658               if(ifx) ifx->generated = 1;
5659             }
5660
5661             return;
5662           }
5663
5664           if(lit & (0x80 << (size*8))) {
5665             /* Lit is less than zero */
5666             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5667             //rFalseIfx.condition ^= 1;
5668             //genSkipCond(&rFalseIfx,left,size,7);
5669             //rFalseIfx.condition ^= 1;
5670             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5671             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5672
5673             if(rFalseIfx.condition)
5674               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5675             else
5676               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5677
5678
5679           } else {
5680             /* Lit is greater than or equal to zero */
5681             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5682             //rFalseIfx.condition ^= 1;
5683             //genSkipCond(&rFalseIfx,right,size,7);
5684             //rFalseIfx.condition ^= 1;
5685
5686             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5687             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5688
5689             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5690             if(rFalseIfx.condition)
5691               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5692             else
5693               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5694
5695           }
5696
5697           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5698           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5699
5700           while(size--) {
5701
5702             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5703             emitSKPNZ;
5704             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705           }
5706           rFalseIfx.condition ^= 1;
5707           //rFalseIfx.condition = 1;
5708           genSkipc(&rFalseIfx);
5709
5710           pic16_emitpLabel(truelbl->key);
5711
5712           if(ifx) ifx->generated = 1;
5713
5714
5715           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5716             goto check_carry;
5717
5718           return;
5719           // end of if (sign)
5720         } else {
5721
5722           /* compare word or long to an unsigned literal on the right.*/
5723
5724
5725           size--;
5726           if(lit < 0xff) {
5727             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5728             switch (lit) {
5729             case 0:
5730               break; /* handled above */
5731 /*
5732             case 0xff:
5733               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5734               while(size--)
5735                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5736               genSkipz2(&rFalseIfx,0);
5737               break;
5738 */
5739             default:
5740               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5741               while(--size)
5742                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5743
5744               emitSKPZ;
5745               if(rFalseIfx.condition)
5746                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5747               else
5748                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5749
5750
5751               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5752               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5753
5754               rFalseIfx.condition ^= 1;
5755               genSkipc(&rFalseIfx);
5756             }
5757
5758             pic16_emitpLabel(truelbl->key);
5759
5760             if(ifx) ifx->generated = 1;
5761
5762             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5763               goto check_carry;
5764
5765             return;
5766           }
5767
5768
5769           lit++;
5770           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5771           i = (lit >> (size*8)) & 0xff;
5772
5773           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5774           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5775
5776           while(size--) {
5777             i = (lit >> (size*8)) & 0xff;
5778
5779             if(i) {
5780               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5781               emitSKPNZ;
5782               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5783             } else {
5784               /* this byte of the lit is zero, 
5785                * if it's not the last then OR in the variable */
5786               if(size)
5787                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5788             }
5789           }
5790
5791
5792           pic16_emitpLabel(lbl->key);
5793
5794           rFalseIfx.condition ^= 1;
5795
5796           genSkipc(&rFalseIfx);
5797         }
5798
5799         if(sign)
5800           pic16_emitpLabel(truelbl->key);
5801         if(ifx) ifx->generated = 1;
5802
5803             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5804               goto check_carry;
5805
5806         return;
5807       }
5808     }
5809     /* Compare two variables */
5810
5811     DEBUGpic16_emitcode(";sign","%d",sign);
5812
5813     size--;
5814     if(sign) {
5815       /* Sigh. thus sucks... */
5816       if(size) {
5817         pCodeOp *pctemp;
5818         
5819         pctemp = pic16_popGetTempReg(1);
5820         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5821         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5822         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5823         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5825         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826         pic16_popReleaseTempReg(pctemp, 1);
5827       } else {
5828         /* Signed char comparison */
5829         /* Special thanks to Nikolai Golovchenko for this snippet */
5830         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5831         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5832         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5833         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5834         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5835         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5836
5837         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5838         genSkipc(&rFalseIfx);
5839           
5840         if(ifx) ifx->generated = 1;
5841
5842             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5843               goto check_carry;
5844
5845         return;
5846       }
5847
5848     } else {
5849
5850       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5851       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5852     }
5853
5854
5855     /* The rest of the bytes of a multi-byte compare */
5856     while (size) {
5857
5858       emitSKPZ;
5859       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5860       size--;
5861
5862       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5863       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5864
5865
5866     }
5867
5868     pic16_emitpLabel(lbl->key);
5869
5870     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5871     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5872         (AOP_TYPE(result) == AOP_REG)) {
5873       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5874       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5875     } else {
5876       genSkipc(&rFalseIfx);
5877     }         
5878     //genSkipc(&rFalseIfx);
5879     if(ifx) ifx->generated = 1;
5880
5881
5882             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5883               goto check_carry;
5884
5885     return;
5886
5887   }
5888
5889 check_carry:
5890   if ((AOP_TYPE(result) != AOP_CRY) 
5891         && AOP_SIZE(result)) {
5892     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5893
5894     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5895
5896     pic16_outBitC(result);
5897   } else {
5898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899     /* if the result is used in the next
5900        ifx conditional branch then generate
5901        code a little differently */
5902     if (ifx )
5903       genIfxJump (ifx,"c");
5904     else
5905       pic16_outBitC(result);
5906     /* leave the result in acc */
5907   }
5908
5909 }
5910
5911 #elif 0 /* VR version of genCmp() */    /* } else { */
5912
5913 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5914 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5915         operand *result, int offset, int invert_op)
5916 {
5917   /* add code here */
5918   
5919   /* check condition, > or < ?? */
5920   if(rIfx->condition != 0)invert_op ^= 1;
5921   
5922   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5923
5924   if(!ifx)invert_op ^= 1;
5925
5926   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5927       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5928   
5929   /* do selection */
5930   if(!invert_op)return POC_CPFSGT;
5931   else return POC_CPFSLT;
5932 }
5933
5934 static int compareAopfirstpass=1;
5935
5936 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5937             operand *oper, int offset, operand *result,
5938             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5939             symbol *tlbl)
5940 {
5941   int op;
5942   symbol *truelbl;
5943
5944   /* invert if there is a result to be loaded, in order to fit,
5945    * SETC/CLRC sequence */
5946   if(AOP_SIZE(result))invert_op ^= 1;
5947
5948 //  if(sign && !offset)invert_op ^= 1;
5949   
5950 //  if(sign)invert_op ^= 1;
5951   
5952   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5953
5954   if(AOP_SIZE(result) && compareAopfirstpass) {
5955     if(!ifx) {
5956       if(pcop2)
5957         pic16_emitpcode(POC_SETF, pcop2);
5958       else
5959         emitSETC;
5960     } else {
5961       if(pcop2)
5962         pic16_emitpcode(POC_CLRF, pcop2);
5963       else
5964         emitCLRC;
5965     }
5966   }
5967
5968   compareAopfirstpass = 0;
5969
5970       /* there is a bug when comparing operands with size > 1,
5971        * because higher bytes can be equal and test should be performed
5972        * to the next lower byte, current algorithm, considers operands
5973        * inequal in these cases! -- VR 20041107 */
5974
5975     
5976   if(pcop)
5977     pic16_emitpcode(op, pcop);
5978   else
5979     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5980
5981
5982   if((!sign || !offset) && AOP_SIZE(result)) {
5983     if(!ifx) {
5984       if(pcop2)
5985         pic16_emitpcode(POC_CLRF, pcop2);
5986         else
5987         emitCLRC;
5988     } else {
5989       if(pcop2)
5990         pic16_emitpcode(POC_SETF, pcop2);
5991       else
5992         emitSETC;
5993     }
5994     
5995     /* don't emit final branch (offset == 0) */
5996     if(offset) {
5997
5998       if(pcop2)
5999         pic16_emitpcode(POC_RRCF, pcop2);
6000
6001       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6002     }
6003   } else {
6004     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6005       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6006             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6007
6008       truelbl = newiTempLabel( NULL );
6009       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6010       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6011         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6012       else
6013         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6014       pic16_emitpLabel(truelbl->key);
6015     } else {
6016       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6017     }
6018   }
6019 }
6020
6021 static void genCmp (operand *left, operand *right,
6022                     operand *result, iCode *ifx, int sign)
6023 {
6024   int size, cmpop=1;
6025   long lit = 0L;
6026   resolvedIfx rFalseIfx;
6027   symbol *falselbl, *tlbl;
6028
6029     FENTRY;
6030     
6031     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6032
6033     resolveIfx(&rFalseIfx, ifx);
6034     size = max(AOP_SIZE(left), AOP_SIZE(right));
6035     
6036     /* if left & right are bit variables */
6037     if(AOP_TYPE(left) == AOP_CRY
6038       && AOP_TYPE(right) == AOP_CRY ) {
6039
6040         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6041         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6042         
6043         werror(W_POSSBUG2, __FILE__, __LINE__);
6044         exit(-1);
6045     }
6046     
6047     /* if literal is on the right then swap with left */
6048     if((AOP_TYPE(right) == AOP_LIT)) {
6049       operand *tmp = right ;
6050 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6051
6052         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6053
6054 //      lit = (lit - 1) & mask;
6055         right = left;
6056         left = tmp;
6057         rFalseIfx.condition ^= 1;               /* reverse compare */
6058     } else
6059     if ((AOP_TYPE(left) == AOP_LIT)) {
6060       /* float compares are handled by support functions */
6061       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6062     }
6063
6064     /* actual comparing algorithm */
6065 //    size = AOP_SIZE( right );
6066
6067     falselbl = newiTempLabel( NULL );
6068     if(AOP_TYPE(left) == AOP_LIT) {
6069       /* compare to literal */
6070       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6071       
6072       if(sign) {
6073         pCodeOp *pct, *pct2;
6074         symbol *tlbl1;
6075
6076         /* signed compare */
6077         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6078
6079         pct = pic16_popCopyReg(&pic16_pc_prodl);
6080         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6081         tlbl = newiTempLabel( NULL );
6082         
6083         /* first compare signs:
6084          *  a. if both are positive, compare just like unsigned
6085          *  b. if both are negative, invert cmpop, compare just like unsigned
6086          *  c. if different signs, determine the result directly */
6087
6088         size--;
6089
6090 #if 1
6091         /* { */
6092         tlbl1 = newiTempLabel( NULL );
6093 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6094
6095         if(lit > 0) {
6096
6097           /* literal is zero or positive:
6098            *  a. if carry is zero, too, continue compare,
6099            *  b. if carry is set, then continue depending on cmpop ^ condition:
6100            *    1. '<' return false (literal < variable),
6101            *    2. '>' return true (literal > variable) */
6102 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6103           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6104           
6105           
6106           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6107           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6108         } else 
6109         if(lit < 0) {
6110           
6111           /* literal is negative:
6112            *  a. if carry is set, too, continue compare,
6113            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6114            *    1. '<' return true (literal < variable),
6115            *    2. '>' return false (literal > variable) */
6116 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6117           pic16_emitpcode(POC_BTFSS, 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 #if 1
6123         else {
6124           /* lit == 0 */
6125           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6126           
6127           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6128           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6129         }
6130 #endif
6131         
6132         
6133         pic16_emitpLabel( tlbl1->key );
6134 #endif  /* } */
6135
6136         compareAopfirstpass=1;
6137 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6138 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6139 //        pic16_emitpcode(POC_MOVWF, pct);
6140
6141 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6142         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6143 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6144         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6145
6146         /* generic case */        
6147           while( size-- ) {
6148 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6149 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6150 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6151 //            pic16_emitpcode(POC_MOVWF, pct);
6152
6153 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6154             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6155             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6156 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6157 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6158           }
6159 //        }
6160         
6161         if(ifx)ifx->generated = 1;
6162
6163         if(AOP_SIZE(result)) {
6164           pic16_emitpLabel(tlbl->key);
6165           pic16_emitpLabel(falselbl->key);
6166           pic16_outBitOp( result, pct2 );
6167         } else {
6168           pic16_emitpLabel(tlbl->key);
6169         }
6170       } else {
6171
6172         /* unsigned compare */      
6173         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6174     
6175         compareAopfirstpass=1;
6176         while(size--) {
6177           
6178           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6179           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6180
6181         }
6182         if(ifx)ifx->generated = 1;
6183
6184         if(AOP_SIZE(result)) {
6185           pic16_emitpLabel(falselbl->key);
6186           pic16_outBitC( result );
6187         }
6188
6189       }
6190     } else {
6191       /* compare registers */
6192       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6193
6194
6195       if(sign) {
6196         pCodeOp *pct, *pct2;
6197         
6198         /* signed compare */
6199         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6200
6201         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6202         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6203         tlbl = newiTempLabel( NULL );
6204         
6205         compareAopfirstpass=1;
6206
6207         size--;
6208         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6209 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6210         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6211         pic16_emitpcode(POC_MOVWF, pct);
6212
6213         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6214 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6215         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6216
6217         /* WREG already holds left + 0x80 */
6218         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6219         
6220         while( size-- ) {
6221           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6222 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6223           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6224           pic16_emitpcode(POC_MOVWF, pct);
6225                 
6226           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6227 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6228           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6229
6230           /* WREG already holds left + 0x80 */
6231           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6232 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6233         }
6234         
6235         if(ifx)ifx->generated = 1;
6236
6237         if(AOP_SIZE(result)) {
6238           pic16_emitpLabel(tlbl->key);
6239           pic16_emitpLabel(falselbl->key);
6240           pic16_outBitOp( result, pct2 );
6241         } else {
6242           pic16_emitpLabel(tlbl->key);
6243         }
6244
6245       } else {
6246         /* unsigned compare */      
6247         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6248
6249         compareAopfirstpass=1;
6250         while(size--) {
6251           
6252           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6253           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6254
6255         }
6256
6257         if(ifx)ifx->generated = 1;
6258         if(AOP_SIZE(result)) {
6259
6260           pic16_emitpLabel(falselbl->key);
6261           pic16_outBitC( result );
6262         }
6263
6264       }
6265     }
6266 }
6267
6268 #endif  /* } */
6269
6270
6271
6272 /*-----------------------------------------------------------------*/
6273 /* genCmpGt :- greater than comparison                             */
6274 /*-----------------------------------------------------------------*/
6275 static void genCmpGt (iCode *ic, iCode *ifx)
6276 {
6277   operand *left, *right, *result;
6278   sym_link *letype , *retype;
6279   int sign ;
6280
6281     FENTRY;
6282     
6283     left = IC_LEFT(ic);
6284     right= IC_RIGHT(ic);
6285     result = IC_RESULT(ic);
6286
6287     letype = getSpec(operandType(left));
6288     retype =getSpec(operandType(right));
6289     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6290     /* assign the amsops */
6291     pic16_aopOp (left,ic,FALSE);
6292     pic16_aopOp (right,ic,FALSE);
6293     pic16_aopOp (result,ic,TRUE);
6294
6295     genCmp(right, left, result, ifx, sign);
6296
6297     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299     pic16_freeAsmop(result,NULL,ic,TRUE); 
6300 }
6301
6302 /*-----------------------------------------------------------------*/
6303 /* genCmpLt - less than comparisons                                */
6304 /*-----------------------------------------------------------------*/
6305 static void genCmpLt (iCode *ic, iCode *ifx)
6306 {
6307   operand *left, *right, *result;
6308   sym_link *letype , *retype;
6309   int sign ;
6310
6311     FENTRY;
6312
6313     left = IC_LEFT(ic);
6314     right= IC_RIGHT(ic);
6315     result = IC_RESULT(ic);
6316
6317     letype = getSpec(operandType(left));
6318     retype =getSpec(operandType(right));
6319     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6320
6321     /* assign the amsops */
6322     pic16_aopOp (left,ic,FALSE);
6323     pic16_aopOp (right,ic,FALSE);
6324     pic16_aopOp (result,ic,TRUE);
6325
6326     genCmp(left, right, result, ifx, sign);
6327
6328     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330     pic16_freeAsmop(result,NULL,ic,TRUE); 
6331 }
6332
6333 #if 0
6334 // not needed ATM
6335 // FIXME reenable literal optimisation when the pic16 port is stable
6336
6337 /*-----------------------------------------------------------------*/
6338 /* genc16bit2lit - compare a 16 bit value to a literal             */
6339 /*-----------------------------------------------------------------*/
6340 static void genc16bit2lit(operand *op, int lit, int offset)
6341 {
6342   int i;
6343
6344   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6345   if( (lit&0xff) == 0) 
6346     i=1;
6347   else
6348     i=0;
6349
6350   switch( BYTEofLONG(lit,i)) { 
6351   case 0:
6352     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6353     break;
6354   case 1:
6355     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6356     break;
6357   case 0xff:
6358     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6359     break;
6360   default:
6361     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6362     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6363   }
6364
6365   i ^= 1;
6366
6367   switch( BYTEofLONG(lit,i)) { 
6368   case 0:
6369     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6370     break;
6371   case 1:
6372     emitSKPNZ;
6373     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6374     break;
6375   case 0xff:
6376     emitSKPNZ;
6377     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6378     break;
6379   default:
6380     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6381     emitSKPNZ;
6382     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6383
6384   }
6385
6386 }
6387 #endif
6388
6389 #if 0
6390 // not needed ATM
6391 /*-----------------------------------------------------------------*/
6392 /* gencjneshort - compare and jump if not equal                    */
6393 /*-----------------------------------------------------------------*/
6394 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6395 {
6396   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6397   int offset = 0;
6398   int res_offset = 0;  /* the result may be a different size then left or right */
6399   int res_size = AOP_SIZE(result);
6400   resolvedIfx rIfx;
6401   symbol *lbl, *lbl_done;
6402
6403   unsigned long lit = 0L;
6404   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6405
6406   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6407   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6408   if(result)
6409     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6410   resolveIfx(&rIfx,ifx);
6411   lbl =  newiTempLabel(NULL);
6412   lbl_done =  newiTempLabel(NULL);
6413
6414
6415   /* if the left side is a literal or 
6416      if the right is in a pointer register and left 
6417      is not */
6418   if ((AOP_TYPE(left) == AOP_LIT) || 
6419       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6420     operand *t = right;
6421     right = left;
6422     left = t;
6423   }
6424   if(AOP_TYPE(right) == AOP_LIT)
6425     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6426
6427   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6428     preserve_result = 1;
6429
6430   if(result && !preserve_result)
6431     {
6432       int i;
6433       for(i = 0; i < AOP_SIZE(result); i++)
6434         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6435     }
6436
6437
6438   /* if the right side is a literal then anything goes */
6439   if (AOP_TYPE(right) == AOP_LIT &&
6440       AOP_TYPE(left) != AOP_DIR ) {
6441     switch(size) {
6442     case 2:
6443       genc16bit2lit(left, lit, 0);
6444       emitSKPZ;
6445       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6446       break;
6447     default:
6448       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6449       while (size--) {
6450         if(lit & 0xff) {
6451           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6452           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6453         } else {
6454           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6455         }
6456
6457         emitSKPZ;
6458         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6459         offset++;
6460         if(res_offset < res_size-1)
6461           res_offset++;
6462         lit >>= 8;
6463       }
6464       break;
6465     }
6466   }
6467
6468   /* if the right side is in a register or in direct space or
6469      if the left is a pointer register & right is not */    
6470   else if (AOP_TYPE(right) == AOP_REG ||
6471            AOP_TYPE(right) == AOP_DIR || 
6472            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6473            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6474     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6475     int lbl_key = lbl->key;
6476
6477     if(result) {
6478       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6479       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6480     }else {
6481       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6482       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6483               __FUNCTION__,__LINE__);
6484       return;
6485     }
6486    
6487 /*     switch(size) { */
6488 /*     case 2: */
6489 /*       genc16bit2lit(left, lit, 0); */
6490 /*       emitSKPNZ; */
6491 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6492 /*       break; */
6493 /*     default: */
6494     while (size--) {
6495       int emit_skip=1;
6496       if((AOP_TYPE(left) == AOP_DIR) && 
6497          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6498
6499         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6500         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6501
6502       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6503             
6504         switch (lit & 0xff) {
6505         case 0:
6506           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6507           break;
6508         case 1:
6509           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6510           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6511           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6512           emit_skip=0;
6513           break;
6514         case 0xff:
6515           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6516           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6518           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6519           emit_skip=0;
6520           break;
6521         default:
6522           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6523           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6524         }
6525         lit >>= 8;
6526
6527       } else {
6528         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6529       }
6530       if(emit_skip) {
6531         if(AOP_TYPE(result) == AOP_CRY) {
6532           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6533           if(rIfx.condition)
6534             emitSKPNZ;
6535           else
6536             emitSKPZ;
6537           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6538         } else {
6539           /* fix me. probably need to check result size too */
6540           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6541           if(rIfx.condition)
6542             emitSKPZ;
6543           else
6544             emitSKPNZ;
6545           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6546           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6547         }
6548         if(ifx)
6549           ifx->generated=1;
6550       }
6551       emit_skip++;
6552       offset++;
6553       if(res_offset < res_size-1)
6554         res_offset++;
6555     }
6556 /*       break; */
6557 /*     } */
6558   } else if(AOP_TYPE(right) == AOP_REG &&
6559             AOP_TYPE(left) != AOP_DIR){
6560
6561     while(size--) {
6562       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6563       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6564       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6565       if(rIfx.condition)
6566         emitSKPNZ;
6567       else
6568         emitSKPZ;
6569       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6570       offset++;
6571       if(res_offset < res_size-1)
6572         res_offset++;
6573     }
6574       
6575   }else{
6576     /* right is a pointer reg need both a & b */
6577     while(size--) {
6578       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6579       if(strcmp(l,"b"))
6580         pic16_emitcode("mov","b,%s",l);
6581       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6582       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6583       offset++;
6584     }
6585   }
6586
6587   if(result && preserve_result)
6588     {
6589       int i;
6590       for(i = 0; i < AOP_SIZE(result); i++)
6591         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6592     }
6593
6594   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6595
6596   if(result && preserve_result)
6597     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6598
6599   if(!rIfx.condition)
6600     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6601
6602   pic16_emitpLabel(lbl->key);
6603
6604   if(result && preserve_result)
6605     {
6606       int i;
6607       for(i = 0; i < AOP_SIZE(result); i++)
6608         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6609
6610       pic16_emitpLabel(lbl_done->key);
6611    }
6612
6613   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6614
6615   if(ifx)
6616     ifx->generated = 1;
6617 }
6618 #endif
6619
6620 #if 0
6621 /*-----------------------------------------------------------------*/
6622 /* gencjne - compare and jump if not equal                         */
6623 /*-----------------------------------------------------------------*/
6624 static void gencjne(operand *left, operand *right, iCode *ifx)
6625 {
6626     symbol *tlbl  = newiTempLabel(NULL);
6627
6628     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6629     gencjneshort(left, right, lbl);
6630
6631     pic16_emitcode("mov","a,%s",one);
6632     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6633     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6634     pic16_emitcode("clr","a");
6635     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6636
6637     pic16_emitpLabel(lbl->key);
6638     pic16_emitpLabel(tlbl->key);
6639
6640 }
6641 #endif
6642
6643
6644 /*-----------------------------------------------------------------*/
6645 /* is_LitOp - check if operand has to be treated as literal        */
6646 /*-----------------------------------------------------------------*/
6647 static bool is_LitOp(operand *op)
6648 {
6649   return ((AOP_TYPE(op) == AOP_LIT)
6650       || ( (AOP_TYPE(op) == AOP_PCODE)
6651           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6652               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6653 }
6654
6655 /*-----------------------------------------------------------------*/
6656 /* is_LitAOp - check if operand has to be treated as literal        */
6657 /*-----------------------------------------------------------------*/
6658 static bool is_LitAOp(asmop *aop)
6659 {
6660   return ((aop->type == AOP_LIT)
6661       || ( (aop->type == AOP_PCODE)
6662           && ( (aop->aopu.pcop->type == PO_LITERAL)
6663               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6664 }
6665
6666
6667
6668 /*-----------------------------------------------------------------*/
6669 /* genCmpEq - generates code for equal to                          */
6670 /*-----------------------------------------------------------------*/
6671 static void genCmpEq (iCode *ic, iCode *ifx)
6672 {
6673   operand *left, *right, *result;
6674   symbol *falselbl = newiTempLabel(NULL);
6675   symbol *donelbl = newiTempLabel(NULL);
6676
6677   int preserve_result = 0;
6678   int generate_result = 0;
6679   int i=0;
6680   unsigned long lit = -1;
6681
6682   FENTRY;
6683   
6684   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6685   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6686   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6687  
6688   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6689
6690   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6691     {
6692       werror(W_POSSBUG2, __FILE__, __LINE__);
6693       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6694       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6695       goto release;
6696     }
6697
6698   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6699     {
6700       operand *tmp = right ;
6701       right = left;
6702       left = tmp;
6703     }
6704
6705   if (AOP_TYPE(right) == AOP_LIT) {
6706     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6707   }
6708
6709   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6710     preserve_result = 1;
6711
6712   if(result && AOP_SIZE(result))
6713     generate_result = 1;
6714
6715   if(generate_result && !preserve_result)
6716     {
6717       for(i = 0; i < AOP_SIZE(result); i++)
6718         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6719     }
6720
6721   for(i=0; i < AOP_SIZE(left); i++)
6722     {
6723       if(AOP_TYPE(left) != AOP_ACC)
6724         {
6725           if(is_LitOp(left))
6726             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6727           else
6728             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6729         }
6730       if(is_LitOp(right)) {
6731         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6732           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6733         }
6734       } else
6735         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6736
6737       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6738     }
6739
6740   // result == true
6741
6742   if(generate_result && preserve_result)
6743     {
6744       for(i = 0; i < AOP_SIZE(result); i++)
6745         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6746     }
6747
6748   if(generate_result)
6749     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6750
6751   if(generate_result && preserve_result)
6752     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6753
6754   if(ifx && IC_TRUE(ifx))
6755     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6756
6757   if(ifx && IC_FALSE(ifx))
6758     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6759
6760   pic16_emitpLabel(falselbl->key);
6761
6762   // result == false
6763
6764   if(ifx && IC_FALSE(ifx))
6765     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6766
6767   if(generate_result && preserve_result)
6768     {
6769       for(i = 0; i < AOP_SIZE(result); i++)
6770         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6771     }
6772
6773   pic16_emitpLabel(donelbl->key);
6774
6775   if(ifx)
6776     ifx->generated = 1;
6777
6778 release:
6779   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6780   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6781   pic16_freeAsmop(result,NULL,ic,TRUE);
6782
6783 }
6784
6785
6786 #if 0
6787 // old version kept for reference
6788
6789 /*-----------------------------------------------------------------*/
6790 /* genCmpEq - generates code for equal to                          */
6791 /*-----------------------------------------------------------------*/
6792 static void genCmpEq (iCode *ic, iCode *ifx)
6793 {
6794     operand *left, *right, *result;
6795     unsigned long lit = 0L;
6796     int size,offset=0;
6797     symbol *falselbl  = newiTempLabel(NULL);
6798
6799
6800     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6801
6802     if(ifx)
6803       DEBUGpic16_emitcode ("; ifx is non-null","");
6804     else
6805       DEBUGpic16_emitcode ("; ifx is null","");
6806
6807     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6808     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6809     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6810
6811     size = max(AOP_SIZE(left),AOP_SIZE(right));
6812
6813     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6814
6815     /* if literal, literal on the right or 
6816     if the right is in a pointer register and left 
6817     is not */
6818     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6819         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6820       operand *tmp = right ;
6821       right = left;
6822       left = tmp;
6823     }
6824
6825
6826     if(ifx && !AOP_SIZE(result)){
6827         symbol *tlbl;
6828         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6829         /* if they are both bit variables */
6830         if (AOP_TYPE(left) == AOP_CRY &&
6831             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6832                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6833             if(AOP_TYPE(right) == AOP_LIT){
6834                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6835                 if(lit == 0L){
6836                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6837                     pic16_emitcode("cpl","c");
6838                 } else if(lit == 1L) {
6839                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840                 } else {
6841                     pic16_emitcode("clr","c");
6842                 }
6843                 /* AOP_TYPE(right) == AOP_CRY */
6844             } else {
6845                 symbol *lbl = newiTempLabel(NULL);
6846                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6847                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6848                 pic16_emitcode("cpl","c");
6849                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6850             }
6851             /* if true label then we jump if condition
6852             supplied is true */
6853             tlbl = newiTempLabel(NULL);
6854             if ( IC_TRUE(ifx) ) {
6855                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6856                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6857             } else {
6858                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6859                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6860             }
6861             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6862
6863                 {
6864                 /* left and right are both bit variables, result is carry */
6865                         resolvedIfx rIfx;
6866               
6867                         resolveIfx(&rIfx,ifx);
6868
6869                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6870                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6871                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6872                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6873                         genSkipz2(&rIfx,0);
6874                 }
6875         } else {
6876
6877                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6878
6879                         /* They're not both bit variables. Is the right a literal? */
6880                         if(AOP_TYPE(right) == AOP_LIT) {
6881                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6882             
6883                         switch(size) {
6884
6885                                 case 1:
6886                                         switch(lit & 0xff) {
6887                                                 case 1:
6888                                                                 if ( IC_TRUE(ifx) ) {
6889                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6890                                                                         emitSKPNZ;
6891                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6892                                                                 } else {
6893                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6894                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6895                                                                 }
6896                                                                 break;
6897                                                 case 0xff:
6898                                                                 if ( IC_TRUE(ifx) ) {
6899                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6900                                                                         emitSKPNZ;
6901                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6902                                                                 } else {
6903                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6904                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6905                                                                 }
6906                                                                 break;
6907                                                 default:
6908                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6909                                                                 if(lit)
6910                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6911                                                                 genSkip(ifx,'z');
6912                                         } // switch lit
6913
6914
6915                                         /* end of size == 1 */
6916                                         break;
6917               
6918                                 case 2:
6919                                         genc16bit2lit(left,lit,offset);
6920                                         genSkip(ifx,'z');
6921                                         break;
6922                                         /* end of size == 2 */
6923
6924                                 default:
6925                                         /* size is 4 */
6926                                         if(lit==0) {
6927                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6928                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6929                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6930                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6931                                                 genSkip(ifx,'z');
6932                                         } else {
6933                                                 /* search for patterns that can be optimized */
6934
6935                                                 genc16bit2lit(left,lit,0);
6936                                                 lit >>= 16;
6937                                                 if(lit) {
6938                                                                 if(IC_TRUE(ifx))
6939                                                                 emitSKPZ; // if hi word unequal
6940                                                                 else
6941                                                                 emitSKPNZ; // if hi word equal
6942                                                                 // fail early
6943                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6944                                                         genc16bit2lit(left,lit,2);
6945                                                         genSkip(ifx,'z');
6946                                                 } else {
6947                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6948                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6949                                                         genSkip(ifx,'z');
6950                                                 }
6951                                         }
6952                                                 pic16_emitpLabel(falselbl->key);
6953                                                 break;
6954
6955                         } // switch size
6956           
6957                         ifx->generated = 1;
6958                         goto release ;
6959             
6960
6961           } else if(AOP_TYPE(right) == AOP_CRY ) {
6962             /* we know the left is not a bit, but that the right is */
6963             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6964             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6965                       pic16_popGet(AOP(right),offset));
6966             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6967
6968             /* if the two are equal, then W will be 0 and the Z bit is set
6969              * we could test Z now, or go ahead and check the high order bytes if
6970              * the variable we're comparing is larger than a byte. */
6971
6972             while(--size)
6973               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6974
6975             if ( IC_TRUE(ifx) ) {
6976               emitSKPNZ;
6977               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6978               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6979             } else {
6980               emitSKPZ;
6981               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6982               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6983             }
6984
6985           } else {
6986             /* They're both variables that are larger than bits */
6987             int s = size;
6988
6989             tlbl = newiTempLabel(NULL);
6990
6991             while(size--) {
6992               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6993               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6994
6995               if ( IC_TRUE(ifx) ) {
6996                 if(size) {
6997                   emitSKPZ;
6998                 
6999                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7000
7001                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7002                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7003                 } else {
7004                   emitSKPNZ;
7005
7006                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7007
7008
7009                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7010                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7011                 }
7012               } else {
7013                 emitSKPZ;
7014
7015                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7016
7017                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7018                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7019               }
7020               offset++;
7021             }
7022             if(s>1 && IC_TRUE(ifx)) {
7023               pic16_emitpLabel(tlbl->key);
7024               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7025             }
7026           }
7027         }
7028         /* mark the icode as generated */
7029         ifx->generated = 1;
7030         goto release ;
7031     }
7032
7033     /* if they are both bit variables */
7034     if (AOP_TYPE(left) == AOP_CRY &&
7035         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7036         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7037         if(AOP_TYPE(right) == AOP_LIT){
7038             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7039             if(lit == 0L){
7040                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7041                 pic16_emitcode("cpl","c");
7042             } else if(lit == 1L) {
7043                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044             } else {
7045                 pic16_emitcode("clr","c");
7046             }
7047             /* AOP_TYPE(right) == AOP_CRY */
7048         } else {
7049             symbol *lbl = newiTempLabel(NULL);
7050             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7051             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7052             pic16_emitcode("cpl","c");
7053             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7054         }
7055         /* c = 1 if egal */
7056         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7057             pic16_outBitC(result);
7058             goto release ;
7059         }
7060         if (ifx) {
7061             genIfxJump (ifx,"c");
7062             goto release ;
7063         }
7064         /* if the result is used in an arithmetic operation
7065         then put the result in place */
7066         pic16_outBitC(result);
7067     } else {
7068       
7069       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7070       gencjne(left,right,result,ifx);
7071 /*
7072       if(ifx) 
7073         gencjne(left,right,newiTempLabel(NULL));
7074       else {
7075         if(IC_TRUE(ifx)->key)
7076           gencjne(left,right,IC_TRUE(ifx)->key);
7077         else
7078           gencjne(left,right,IC_FALSE(ifx)->key);
7079         ifx->generated = 1;
7080         goto release ;
7081       }
7082       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7083         pic16_aopPut(AOP(result),"a",0);
7084         goto release ;
7085       }
7086
7087       if (ifx) {
7088         genIfxJump (ifx,"a");
7089         goto release ;
7090       }
7091 */
7092       /* if the result is used in an arithmetic operation
7093          then put the result in place */
7094 /*
7095       if (AOP_TYPE(result) != AOP_CRY) 
7096         pic16_outAcc(result);
7097 */
7098       /* leave the result in acc */
7099     }
7100
7101 release:
7102     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7103     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7104     pic16_freeAsmop(result,NULL,ic,TRUE);
7105 }
7106 #endif
7107
7108 /*-----------------------------------------------------------------*/
7109 /* ifxForOp - returns the icode containing the ifx for operand     */
7110 /*-----------------------------------------------------------------*/
7111 static iCode *ifxForOp ( operand *op, iCode *ic )
7112 {
7113   FENTRY2;
7114
7115     /* if true symbol then needs to be assigned */
7116     if (IS_TRUE_SYMOP(op))
7117         return NULL ;
7118
7119     /* if this has register type condition and
7120     the next instruction is ifx with the same operand
7121     and live to of the operand is upto the ifx only then */
7122     if (ic->next
7123         && ic->next->op == IFX
7124         && IC_COND(ic->next)->key == op->key
7125         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7126         ) {
7127                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7128           return ic->next;
7129     }
7130
7131     /*
7132     if (ic->next &&
7133         ic->next->op == IFX &&
7134         IC_COND(ic->next)->key == op->key) {
7135       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7136       return ic->next;
7137     }
7138     */
7139
7140     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7141     if (ic->next &&
7142         ic->next->op == IFX)
7143       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7144
7145     if (ic->next &&
7146         ic->next->op == IFX &&
7147         IC_COND(ic->next)->key == op->key) {
7148       DEBUGpic16_emitcode ("; "," key is okay");
7149       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7150                            OP_SYMBOL(op)->liveTo,
7151                            ic->next->seq);
7152     }
7153
7154 #if 0
7155     /* the code below is completely untested
7156      * it just allows ulong2fs.c compile -- VR */
7157          
7158     ic = ic->next;
7159     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7160                                         __FILE__, __FUNCTION__, __LINE__);
7161         
7162     /* if this has register type condition and
7163     the next instruction is ifx with the same operand
7164     and live to of the operand is upto the ifx only then */
7165     if (ic->next &&
7166         ic->next->op == IFX &&
7167         IC_COND(ic->next)->key == op->key &&
7168         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7169         return ic->next;
7170
7171     if (ic->next &&
7172         ic->next->op == IFX &&
7173         IC_COND(ic->next)->key == op->key) {
7174       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7175       return ic->next;
7176     }
7177
7178     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7179                                         __FILE__, __FUNCTION__, __LINE__);
7180
7181 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7182 #endif
7183
7184     return NULL;
7185 }
7186 /*-----------------------------------------------------------------*/
7187 /* genAndOp - for && operation                                     */
7188 /*-----------------------------------------------------------------*/
7189 static void genAndOp (iCode *ic)
7190 {
7191   operand *left,*right, *result;
7192 /*     symbol *tlbl; */
7193
7194     FENTRY;
7195
7196     /* note here that && operations that are in an
7197     if statement are taken away by backPatchLabels
7198     only those used in arthmetic operations remain */
7199     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7200     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7201     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7202
7203     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7204
7205     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7206     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7207     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7208
7209     /* if both are bit variables */
7210 /*     if (AOP_TYPE(left) == AOP_CRY && */
7211 /*         AOP_TYPE(right) == AOP_CRY ) { */
7212 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7213 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7214 /*         pic16_outBitC(result); */
7215 /*     } else { */
7216 /*         tlbl = newiTempLabel(NULL); */
7217 /*         pic16_toBoolean(left);     */
7218 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7219 /*         pic16_toBoolean(right); */
7220 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7221 /*         pic16_outBitAcc(result); */
7222 /*     } */
7223
7224     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7225     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226     pic16_freeAsmop(result,NULL,ic,TRUE);
7227 }
7228
7229
7230 /*-----------------------------------------------------------------*/
7231 /* genOrOp - for || operation                                      */
7232 /*-----------------------------------------------------------------*/
7233 /*
7234   tsd pic port -
7235   modified this code, but it doesn't appear to ever get called
7236 */
7237
7238 static void genOrOp (iCode *ic)
7239 {
7240   operand *left,*right, *result;
7241   symbol *tlbl;
7242
7243     FENTRY;  
7244
7245   /* note here that || operations that are in an
7246     if statement are taken away by backPatchLabels
7247     only those used in arthmetic operations remain */
7248     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7249     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7250     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7251
7252     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7253
7254     /* if both are bit variables */
7255     if (AOP_TYPE(left) == AOP_CRY &&
7256         AOP_TYPE(right) == AOP_CRY ) {
7257       pic16_emitcode("clrc","");
7258       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7259                AOP(left)->aopu.aop_dir,
7260                AOP(left)->aopu.aop_dir);
7261       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7262                AOP(right)->aopu.aop_dir,
7263                AOP(right)->aopu.aop_dir);
7264       pic16_emitcode("setc","");
7265
7266     } else {
7267         tlbl = newiTempLabel(NULL);
7268         pic16_toBoolean(left);
7269         emitSKPZ;
7270         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7271         pic16_toBoolean(right);
7272         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7273
7274         pic16_outBitAcc(result);
7275     }
7276
7277     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7278     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7279     pic16_freeAsmop(result,NULL,ic,TRUE);            
7280 }
7281
7282 /*-----------------------------------------------------------------*/
7283 /* isLiteralBit - test if lit == 2^n                               */
7284 /*-----------------------------------------------------------------*/
7285 static int isLiteralBit(unsigned long lit)
7286 {
7287     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7288     0x100L,0x200L,0x400L,0x800L,
7289     0x1000L,0x2000L,0x4000L,0x8000L,
7290     0x10000L,0x20000L,0x40000L,0x80000L,
7291     0x100000L,0x200000L,0x400000L,0x800000L,
7292     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7293     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7294     int idx;
7295     
7296     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7297     for(idx = 0; idx < 32; idx++)
7298         if(lit == pw[idx])
7299             return idx+1;
7300     return 0;
7301 }
7302
7303 /*-----------------------------------------------------------------*/
7304 /* continueIfTrue -                                                */
7305 /*-----------------------------------------------------------------*/
7306 static void continueIfTrue (iCode *ic)
7307 {
7308   FENTRY;
7309   if(IC_TRUE(ic))
7310     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7311   ic->generated = 1;
7312 }
7313
7314 /*-----------------------------------------------------------------*/
7315 /* jmpIfTrue -                                                     */
7316 /*-----------------------------------------------------------------*/
7317 static void jumpIfTrue (iCode *ic)
7318 {
7319   FENTRY;
7320   if(!IC_TRUE(ic))
7321     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7322   ic->generated = 1;
7323 }
7324
7325 /*-----------------------------------------------------------------*/
7326 /* jmpTrueOrFalse -                                                */
7327 /*-----------------------------------------------------------------*/
7328 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7329 {
7330   // ugly but optimized by peephole
7331   FENTRY;
7332   if(IC_TRUE(ic)){
7333     symbol *nlbl = newiTempLabel(NULL);
7334       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7335       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7336       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7337       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7338   } else {
7339     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7340     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7341   }
7342   ic->generated = 1;
7343 }
7344
7345 /*-----------------------------------------------------------------*/
7346 /* genAnd  - code for and                                          */
7347 /*-----------------------------------------------------------------*/
7348 static void genAnd (iCode *ic, iCode *ifx)
7349 {
7350   operand *left, *right, *result;
7351   int size, offset=0;  
7352   unsigned long lit = 0L;
7353   int bytelit = 0;
7354   resolvedIfx rIfx;
7355
7356     FENTRY;
7357     
7358   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7359   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7360   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7361
7362   resolveIfx(&rIfx,ifx);
7363
7364   /* if left is a literal & right is not then exchange them */
7365   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7366       AOP_NEEDSACC(left)) {
7367     operand *tmp = right ;
7368     right = left;
7369     left = tmp;
7370   }
7371
7372   /* if result = right then exchange them */
7373   if(pic16_sameRegs(AOP(result),AOP(right))){
7374     operand *tmp = right ;
7375     right = left;
7376     left = tmp;
7377   }
7378
7379   /* if right is bit then exchange them */
7380   if (AOP_TYPE(right) == AOP_CRY &&
7381       AOP_TYPE(left) != AOP_CRY){
7382     operand *tmp = right ;
7383     right = left;
7384     left = tmp;
7385   }
7386   if(AOP_TYPE(right) == AOP_LIT)
7387     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7388
7389   size = AOP_SIZE(result);
7390
7391   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7392
7393   // if(bit & yy)
7394   // result = bit & yy;
7395   if (AOP_TYPE(left) == AOP_CRY){
7396     // c = bit & literal;
7397     if(AOP_TYPE(right) == AOP_LIT){
7398       if(lit & 1) {
7399         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7400           // no change
7401           goto release;
7402         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7403       } else {
7404         // bit(result) = 0;
7405         if(size && (AOP_TYPE(result) == AOP_CRY)){
7406           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7407           goto release;
7408         }
7409         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7410           jumpIfTrue(ifx);
7411           goto release;
7412         }
7413         pic16_emitcode("clr","c");
7414       }
7415     } else {
7416       if (AOP_TYPE(right) == AOP_CRY){
7417         // c = bit & bit;
7418         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7419         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7420       } else {
7421         // c = bit & val;
7422         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7423         // c = lsb
7424         pic16_emitcode("rrc","a");
7425         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7426       }
7427     }
7428     // bit = c
7429     // val = c
7430     if(size)
7431       pic16_outBitC(result);
7432     // if(bit & ...)
7433     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7434       genIfxJump(ifx, "c");           
7435     goto release ;
7436   }
7437
7438   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7439   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7440   if((AOP_TYPE(right) == AOP_LIT) &&
7441      (AOP_TYPE(result) == AOP_CRY) &&
7442      (AOP_TYPE(left) != AOP_CRY)){
7443     int posbit = isLiteralBit(lit);
7444     /* left &  2^n */
7445     if(posbit){
7446       posbit--;
7447       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7448       // bit = left & 2^n
7449       if(size)
7450         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7451       // if(left &  2^n)
7452       else{
7453         if(ifx){
7454 /*
7455           if(IC_TRUE(ifx)) {
7456             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7457             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7458           } else {
7459             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7461           }
7462 */
7463         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7464         size = AOP_SIZE(left);
7465
7466         {
7467           int bp = posbit, ofs=0;
7468           
7469             while(bp > 7) {
7470               bp -= 8;
7471               ofs++;
7472             }
7473         
7474           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7475                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7476
7477         }
7478 /*
7479           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7480                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7481 */
7482           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7483           
7484           ifx->generated = 1;
7485         }
7486         goto release;
7487       }
7488     } else {
7489       symbol *tlbl = newiTempLabel(NULL);
7490       int sizel = AOP_SIZE(left);
7491
7492       if(size)
7493         emitSETC;
7494
7495       while(sizel--) {
7496         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7497
7498           /* patch provided by Aaron Colwell */
7499           if((posbit = isLiteralBit(bytelit)) != 0) {
7500               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7501                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7502                                                 (posbit-1),0, PO_GPR_REGISTER));
7503
7504               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7505 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7506           } else {
7507               if (bytelit == 0xff) {
7508                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7509                    * a peephole could optimize it out -- VR */
7510                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7511               } else {
7512                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7513                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7514               }
7515
7516               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7517                             pic16_popGetLabel(tlbl->key));
7518           }
7519         
7520 #if 0
7521           /* old code, left here for reference -- VR 09/2004 */
7522           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7523           // byte ==  2^n ?
7524           if((posbit = isLiteralBit(bytelit)) != 0)
7525             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7526           else{
7527             if(bytelit != 0x0FFL)
7528               pic16_emitcode("anl","a,%s",
7529                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7530             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7531           }
7532 #endif
7533         }
7534         offset++;
7535       }
7536       // bit = left & literal
7537       if(size) {
7538         emitCLRC;
7539         pic16_emitpLabel(tlbl->key);
7540       }
7541       // if(left & literal)
7542       else {
7543         if(ifx) {
7544           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7545           ifx->generated = 1;
7546         }
7547         pic16_emitpLabel(tlbl->key);
7548         goto release;
7549       }
7550     }
7551
7552     pic16_outBitC(result);
7553     goto release ;
7554   }
7555
7556   /* if left is same as result */
7557   if(pic16_sameRegs(AOP(result),AOP(left))){
7558     int know_W = -1;
7559     for(;size--; offset++,lit>>=8) {
7560       if(AOP_TYPE(right) == AOP_LIT){
7561         switch(lit & 0xff) {
7562         case 0x00:
7563           /*  and'ing with 0 has clears the result */
7564 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7565           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7566           break;
7567         case 0xff:
7568           /* and'ing with 0xff is a nop when the result and left are the same */
7569           break;
7570
7571         default:
7572           {
7573             int p = pic16_my_powof2( (~lit) & 0xff );
7574             if(p>=0) {
7575               /* only one bit is set in the literal, so use a bcf instruction */
7576 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7577               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7578
7579             } else {
7580               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7581               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7582               if(know_W != (lit&0xff))
7583                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7584               know_W = lit &0xff;
7585               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7586             }
7587           }    
7588         }
7589       } else {
7590         if (AOP_TYPE(left) == AOP_ACC) {
7591           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7592         } else {                    
7593           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7594           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7595
7596         }
7597       }
7598     }
7599
7600   } else {
7601     // left & result in different registers
7602     if(AOP_TYPE(result) == AOP_CRY){
7603       // result = bit
7604       // if(size), result in bit
7605       // if(!size && ifx), conditional oper: if(left & right)
7606       symbol *tlbl = newiTempLabel(NULL);
7607       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7608       if(size)
7609         pic16_emitcode("setb","c");
7610       while(sizer--){
7611         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7612         pic16_emitcode("anl","a,%s",
7613                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7614         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7615         offset++;
7616       }
7617       if(size){
7618         CLRC;
7619         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7620         pic16_outBitC(result);
7621       } else if(ifx)
7622         jmpTrueOrFalse(ifx, tlbl);
7623     } else {
7624       for(;(size--);offset++) {
7625         // normal case
7626         // result = left & right
7627         if(AOP_TYPE(right) == AOP_LIT){
7628           int t = (lit >> (offset*8)) & 0x0FFL;
7629           switch(t) { 
7630           case 0x00:
7631             pic16_emitcode("clrf","%s",
7632                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7633             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7634             break;
7635           case 0xff:
7636             pic16_emitcode("movf","%s,w",
7637                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7638             pic16_emitcode("movwf","%s",
7639                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7641             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7642             break;
7643           default:
7644             pic16_emitcode("movlw","0x%x",t);
7645             pic16_emitcode("andwf","%s,w",
7646                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7647             pic16_emitcode("movwf","%s",
7648                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7649               
7650             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7651             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7652             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7653           }
7654           continue;
7655         }
7656
7657         if (AOP_TYPE(left) == AOP_ACC) {
7658           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7659           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7660         } else {
7661           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7662           pic16_emitcode("andwf","%s,w",
7663                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7664           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7665           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7666         }
7667         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7668         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7669       }
7670     }
7671   }
7672
7673   release :
7674     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676   pic16_freeAsmop(result,NULL,ic,TRUE);     
7677 }
7678
7679 /*-----------------------------------------------------------------*/
7680 /* genOr  - code for or                                            */
7681 /*-----------------------------------------------------------------*/
7682 static void genOr (iCode *ic, iCode *ifx)
7683 {
7684     operand *left, *right, *result;
7685     int size, offset=0;
7686     unsigned long lit = 0L;
7687
7688     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7689
7690     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7691     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7692     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7693
7694     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7695
7696     /* if left is a literal & right is not then exchange them */
7697     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7698         AOP_NEEDSACC(left)) {
7699         operand *tmp = right ;
7700         right = left;
7701         left = tmp;
7702     }
7703
7704     /* if result = right then exchange them */
7705     if(pic16_sameRegs(AOP(result),AOP(right))){
7706         operand *tmp = right ;
7707         right = left;
7708         left = tmp;
7709     }
7710
7711     /* if right is bit then exchange them */
7712     if (AOP_TYPE(right) == AOP_CRY &&
7713         AOP_TYPE(left) != AOP_CRY){
7714         operand *tmp = right ;
7715         right = left;
7716         left = tmp;
7717     }
7718
7719     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7720
7721     if(AOP_TYPE(right) == AOP_LIT)
7722         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7723
7724     size = AOP_SIZE(result);
7725
7726     // if(bit | yy)
7727     // xx = bit | yy;
7728     if (AOP_TYPE(left) == AOP_CRY){
7729         if(AOP_TYPE(right) == AOP_LIT){
7730             // c = bit & literal;
7731             if(lit){
7732                 // lit != 0 => result = 1
7733                 if(AOP_TYPE(result) == AOP_CRY){
7734                   if(size)
7735                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7736                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7737                   //     AOP(result)->aopu.aop_dir,
7738                   //     AOP(result)->aopu.aop_dir);
7739                     else if(ifx)
7740                         continueIfTrue(ifx);
7741                     goto release;
7742                 }
7743             } else {
7744                 // lit == 0 => result = left
7745                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7746                     goto release;
7747                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7748             }
7749         } else {
7750             if (AOP_TYPE(right) == AOP_CRY){
7751               if(pic16_sameRegs(AOP(result),AOP(left))){
7752                 // c = bit | bit;
7753                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7754                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7755                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7756
7757                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7758                          AOP(result)->aopu.aop_dir,
7759                          AOP(result)->aopu.aop_dir);
7760                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7761                          AOP(right)->aopu.aop_dir,
7762                          AOP(right)->aopu.aop_dir);
7763                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7764                          AOP(result)->aopu.aop_dir,
7765                          AOP(result)->aopu.aop_dir);
7766               } else {
7767                 if( AOP_TYPE(result) == AOP_ACC) {
7768                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7769                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7770                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7771                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7772
7773                 } else {
7774
7775                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7776                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7779
7780                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7781                                  AOP(result)->aopu.aop_dir,
7782                                  AOP(result)->aopu.aop_dir);
7783                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7784                                  AOP(right)->aopu.aop_dir,
7785                                  AOP(right)->aopu.aop_dir);
7786                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7787                                  AOP(left)->aopu.aop_dir,
7788                                  AOP(left)->aopu.aop_dir);
7789                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7790                                  AOP(result)->aopu.aop_dir,
7791                                  AOP(result)->aopu.aop_dir);
7792                 }
7793               }
7794             } else {
7795                 // c = bit | val;
7796                 symbol *tlbl = newiTempLabel(NULL);
7797                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7798
7799
7800                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7801                 if( AOP_TYPE(right) == AOP_ACC) {
7802                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7803                   emitSKPNZ;
7804                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7805                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7806                 }
7807
7808
7809
7810                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7811                     pic16_emitcode(";XXX setb","c");
7812                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7813                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7814                 pic16_toBoolean(right);
7815                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7816                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7817                     jmpTrueOrFalse(ifx, tlbl);
7818                     goto release;
7819                 } else {
7820                     CLRC;
7821                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7822                 }
7823             }
7824         }
7825         // bit = c
7826         // val = c
7827         if(size)
7828             pic16_outBitC(result);
7829         // if(bit | ...)
7830         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7831             genIfxJump(ifx, "c");           
7832         goto release ;
7833     }
7834
7835     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7836     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7837     if((AOP_TYPE(right) == AOP_LIT) &&
7838        (AOP_TYPE(result) == AOP_CRY) &&
7839        (AOP_TYPE(left) != AOP_CRY)){
7840         if(lit){
7841           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7842             // result = 1
7843             if(size)
7844                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7845             else 
7846                 continueIfTrue(ifx);
7847             goto release;
7848         } else {
7849           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7850             // lit = 0, result = boolean(left)
7851             if(size)
7852                 pic16_emitcode(";XXX setb","c");
7853             pic16_toBoolean(right);
7854             if(size){
7855                 symbol *tlbl = newiTempLabel(NULL);
7856                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7857                 CLRC;
7858                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7859             } else {
7860                 genIfxJump (ifx,"a");
7861                 goto release;
7862             }
7863         }
7864         pic16_outBitC(result);
7865         goto release ;
7866     }
7867
7868     /* if left is same as result */
7869     if(pic16_sameRegs(AOP(result),AOP(left))){
7870       int know_W = -1;
7871       for(;size--; offset++,lit>>=8) {
7872         if(AOP_TYPE(right) == AOP_LIT){
7873           if((lit & 0xff) == 0)
7874             /*  or'ing with 0 has no effect */
7875             continue;
7876           else {
7877             int p = pic16_my_powof2(lit & 0xff);
7878             if(p>=0) {
7879               /* only one bit is set in the literal, so use a bsf instruction */
7880               pic16_emitpcode(POC_BSF,
7881                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7882             } else {
7883               if(know_W != (lit & 0xff))
7884                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7885               know_W = lit & 0xff;
7886               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7887             }
7888                     
7889           }
7890         } else {
7891           if (AOP_TYPE(left) == AOP_ACC) {
7892             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7893             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894           } else {                  
7895             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7896             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7897
7898             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7899             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900
7901           }
7902         }
7903       }
7904     } else {
7905         // left & result in different registers
7906         if(AOP_TYPE(result) == AOP_CRY){
7907             // result = bit
7908             // if(size), result in bit
7909             // if(!size && ifx), conditional oper: if(left | right)
7910             symbol *tlbl = newiTempLabel(NULL);
7911             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7912             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7913
7914
7915             if(size)
7916                 pic16_emitcode(";XXX setb","c");
7917             while(sizer--){
7918                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919                 pic16_emitcode(";XXX orl","a,%s",
7920                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7922                 offset++;
7923             }
7924             if(size){
7925                 CLRC;
7926                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7927                 pic16_outBitC(result);
7928             } else if(ifx)
7929                 jmpTrueOrFalse(ifx, tlbl);
7930         } else for(;(size--);offset++){
7931           // normal case
7932           // result = left & right
7933           if(AOP_TYPE(right) == AOP_LIT){
7934             int t = (lit >> (offset*8)) & 0x0FFL;
7935             switch(t) { 
7936             case 0x00:
7937               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7938               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7939
7940               pic16_emitcode("movf","%s,w",
7941                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7942               pic16_emitcode("movwf","%s",
7943                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7944               break;
7945             default:
7946               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7947               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7948               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7949
7950               pic16_emitcode("movlw","0x%x",t);
7951               pic16_emitcode("iorwf","%s,w",
7952                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7953               pic16_emitcode("movwf","%s",
7954                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7955               
7956             }
7957             continue;
7958           }
7959
7960           // faster than result <- left, anl result,right
7961           // and better if result is SFR
7962           if (AOP_TYPE(left) == AOP_ACC) {
7963             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7964             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965           } else {
7966             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7967             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7968
7969             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7970             pic16_emitcode("iorwf","%s,w",
7971                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7972           }
7973           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7974           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7975         }
7976     }
7977
7978 release :
7979     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7980     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7981     pic16_freeAsmop(result,NULL,ic,TRUE);     
7982 }
7983
7984 /*-----------------------------------------------------------------*/
7985 /* genXor - code for xclusive or                                   */
7986 /*-----------------------------------------------------------------*/
7987 static void genXor (iCode *ic, iCode *ifx)
7988 {
7989   operand *left, *right, *result;
7990   int size, offset=0;
7991   unsigned long lit = 0L;
7992
7993   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7994
7995   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7996   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7997   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7998
7999   /* if left is a literal & right is not ||
8000      if left needs acc & right does not */
8001   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8002       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8003     operand *tmp = right ;
8004     right = left;
8005     left = tmp;
8006   }
8007
8008   /* if result = right then exchange them */
8009   if(pic16_sameRegs(AOP(result),AOP(right))){
8010     operand *tmp = right ;
8011     right = left;
8012     left = tmp;
8013   }
8014
8015   /* if right is bit then exchange them */
8016   if (AOP_TYPE(right) == AOP_CRY &&
8017       AOP_TYPE(left) != AOP_CRY){
8018     operand *tmp = right ;
8019     right = left;
8020     left = tmp;
8021   }
8022   if(AOP_TYPE(right) == AOP_LIT)
8023     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8024
8025   size = AOP_SIZE(result);
8026
8027   // if(bit ^ yy)
8028   // xx = bit ^ yy;
8029   if (AOP_TYPE(left) == AOP_CRY){
8030     if(AOP_TYPE(right) == AOP_LIT){
8031       // c = bit & literal;
8032       if(lit>>1){
8033         // lit>>1  != 0 => result = 1
8034         if(AOP_TYPE(result) == AOP_CRY){
8035           if(size)
8036             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8037             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8038           else if(ifx)
8039             continueIfTrue(ifx);
8040           goto release;
8041         }
8042         pic16_emitcode("setb","c");
8043       } else{
8044         // lit == (0 or 1)
8045         if(lit == 0){
8046           // lit == 0, result = left
8047           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8048             goto release;
8049           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8050         } else{
8051           // lit == 1, result = not(left)
8052           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8053             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8054             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8055             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8056             goto release;
8057           } else {
8058             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8059             pic16_emitcode("cpl","c");
8060           }
8061         }
8062       }
8063
8064     } else {
8065       // right != literal
8066       symbol *tlbl = newiTempLabel(NULL);
8067       if (AOP_TYPE(right) == AOP_CRY){
8068         // c = bit ^ bit;
8069         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8070       }
8071       else{
8072         int sizer = AOP_SIZE(right);
8073         // c = bit ^ val
8074         // if val>>1 != 0, result = 1
8075         pic16_emitcode("setb","c");
8076         while(sizer){
8077           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8078           if(sizer == 1)
8079             // test the msb of the lsb
8080             pic16_emitcode("anl","a,#0xfe");
8081           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8082           sizer--;
8083         }
8084         // val = (0,1)
8085         pic16_emitcode("rrc","a");
8086       }
8087       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8088       pic16_emitcode("cpl","c");
8089       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8090     }
8091     // bit = c
8092     // val = c
8093     if(size)
8094       pic16_outBitC(result);
8095     // if(bit | ...)
8096     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8097       genIfxJump(ifx, "c");           
8098     goto release ;
8099   }
8100
8101   if(pic16_sameRegs(AOP(result),AOP(left))){
8102     /* if left is same as result */
8103     for(;size--; offset++) {
8104       if(AOP_TYPE(right) == AOP_LIT){
8105         int t  = (lit >> (offset*8)) & 0x0FFL;
8106         if(t == 0x00L)
8107           continue;
8108         else
8109           if (IS_AOP_PREG(left)) {
8110             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8111             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8112             pic16_aopPut(AOP(result),"a",offset);
8113           } else {
8114             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8115             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8116             pic16_emitcode("xrl","%s,%s",
8117                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8118                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8119           }
8120       } else {
8121         if (AOP_TYPE(left) == AOP_ACC)
8122           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8123         else {
8124           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8125           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8126 /*
8127           if (IS_AOP_PREG(left)) {
8128             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8129             pic16_aopPut(AOP(result),"a",offset);
8130           } else
8131             pic16_emitcode("xrl","%s,a",
8132                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8133 */
8134         }
8135       }
8136     }
8137   } else {
8138     // left & result in different registers
8139     if(AOP_TYPE(result) == AOP_CRY){
8140       // result = bit
8141       // if(size), result in bit
8142       // if(!size && ifx), conditional oper: if(left ^ right)
8143       symbol *tlbl = newiTempLabel(NULL);
8144       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8145       if(size)
8146         pic16_emitcode("setb","c");
8147       while(sizer--){
8148         if((AOP_TYPE(right) == AOP_LIT) &&
8149            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8150           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8151         } else {
8152           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8153           pic16_emitcode("xrl","a,%s",
8154                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155         }
8156         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8157         offset++;
8158       }
8159       if(size){
8160         CLRC;
8161         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8162         pic16_outBitC(result);
8163       } else if(ifx)
8164         jmpTrueOrFalse(ifx, tlbl);
8165     } else for(;(size--);offset++){
8166       // normal case
8167       // result = left & right
8168       if(AOP_TYPE(right) == AOP_LIT){
8169         int t = (lit >> (offset*8)) & 0x0FFL;
8170         switch(t) { 
8171         case 0x00:
8172           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8173           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8174           pic16_emitcode("movf","%s,w",
8175                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8176           pic16_emitcode("movwf","%s",
8177                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8178           break;
8179         case 0xff:
8180           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8181           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8182           pic16_emitcode("comf","%s,w",
8183                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8184           pic16_emitcode("movwf","%s",
8185                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8186           break;
8187         default:
8188           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8189           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8190           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8191           pic16_emitcode("movlw","0x%x",t);
8192           pic16_emitcode("xorwf","%s,w",
8193                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8194           pic16_emitcode("movwf","%s",
8195                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8196
8197         }
8198         continue;
8199       }
8200
8201       // faster than result <- left, anl result,right
8202       // and better if result is SFR
8203       if (AOP_TYPE(left) == AOP_ACC) {
8204         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8205         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8206       } else {
8207         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8208         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8209         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8210         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8211       }
8212       if ( AOP_TYPE(result) != AOP_ACC){
8213         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8214         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8215       }
8216     }
8217   }
8218
8219   release :
8220     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8221   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8222   pic16_freeAsmop(result,NULL,ic,TRUE);     
8223 }
8224
8225 /*-----------------------------------------------------------------*/
8226 /* genInline - write the inline code out                           */
8227 /*-----------------------------------------------------------------*/
8228 static void genInline (iCode *ic)
8229 {
8230   char *buffer, *bp, *bp1;
8231     
8232         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8233
8234         _G.inLine += (!options.asmpeep);
8235
8236         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8237         strcpy(buffer,IC_INLINE(ic));
8238         
8239         while((bp1=strstr(bp, "\\n"))) {
8240           *bp1++ = '\n';
8241           *bp1++ = ' ';
8242           bp = bp1;
8243         }
8244         bp = bp1 = buffer;
8245
8246 #if 0
8247   /* This is an experimental code for #pragma inline
8248      and is temporarily disabled for 2.5.0 release */
8249         if(asmInlineMap)
8250         {
8251           symbol *sym;
8252           char *s;
8253           char *cbuf;
8254           int cblen;
8255
8256             cbuf = Safe_strdup(buffer);
8257             cblen = strlen(buffer)+1;
8258             memset(cbuf, 0, cblen);
8259
8260             bp = buffer;
8261             bp1 = cbuf;
8262             while(*bp) {
8263               if(*bp != '%')*bp1++ = *bp++;
8264               else {
8265                 int i;
8266
8267                   bp++;
8268                   i = *bp - '0';
8269                   if(i>elementsInSet(asmInlineMap))break;
8270                   
8271                   bp++;
8272                   s = indexSet(asmInlineMap, i);
8273                   DEBUGpc("searching symbol s = `%s'", s);
8274                   sym = findSym(SymbolTab, NULL, s);
8275
8276                   if(sym->reqv) {
8277                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8278                   } else {
8279                     strcat(bp1, sym->rname);
8280                   }
8281                   
8282                   while(*bp1)bp1++;
8283               }
8284               
8285               if(strlen(bp1) > cblen - 16) {
8286                 int i = strlen(cbuf);
8287                 cblen += 50;
8288                 cbuf = realloc(cbuf, cblen);
8289                 memset(cbuf+i, 0, 50);
8290                 bp1 = cbuf + i;
8291               }
8292             }
8293             
8294             free(buffer);
8295             buffer = Safe_strdup( cbuf );
8296             free(cbuf);
8297             
8298             bp = bp1 = buffer;
8299         }
8300 #endif  /* 0 */
8301
8302         /* emit each line as a code */
8303         while (*bp) {
8304                 if (*bp == '\n') {
8305                         *bp++ = '\0';
8306
8307                         if(*bp1)
8308                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8309                         bp1 = bp;
8310                 } else {
8311                         if (*bp == ':') {
8312                                 bp++;
8313                                 *bp = '\0';
8314                                 bp++;
8315
8316                                 /* print label, use this special format with NULL directive
8317                                  * to denote that the argument should not be indented with tab */
8318                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8319                                 bp1 = bp;
8320                         } else
8321                                 bp++;
8322                 }
8323         }
8324
8325         if ((bp1 != bp) && *bp1)
8326                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8327
8328
8329     Safe_free(buffer);
8330
8331     _G.inLine -= (!options.asmpeep);
8332 }
8333
8334 /*-----------------------------------------------------------------*/
8335 /* genRRC - rotate right with carry                                */
8336 /*-----------------------------------------------------------------*/
8337 static void genRRC (iCode *ic)
8338 {
8339   operand *left , *result ;
8340   int size, offset = 0, same;
8341
8342   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8343
8344   /* rotate right with carry */
8345   left = IC_LEFT(ic);
8346   result=IC_RESULT(ic);
8347   pic16_aopOp (left,ic,FALSE);
8348   pic16_aopOp (result,ic,TRUE);
8349
8350   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8351
8352   same = pic16_sameRegs(AOP(result),AOP(left));
8353
8354   size = AOP_SIZE(result);    
8355
8356   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8357
8358   /* get the lsb and put it into the carry */
8359   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8360
8361   offset = 0 ;
8362
8363   while(size--) {
8364
8365     if(same) {
8366       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8367     } else {
8368       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8369       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8370     }
8371
8372     offset++;
8373   }
8374
8375   pic16_freeAsmop(left,NULL,ic,TRUE);
8376   pic16_freeAsmop(result,NULL,ic,TRUE);
8377 }
8378
8379 /*-----------------------------------------------------------------*/
8380 /* genRLC - generate code for rotate left with carry               */
8381 /*-----------------------------------------------------------------*/
8382 static void genRLC (iCode *ic)
8383 {    
8384   operand *left , *result ;
8385   int size, offset = 0;
8386   int same;
8387
8388   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8389   /* rotate right with carry */
8390   left = IC_LEFT(ic);
8391   result=IC_RESULT(ic);
8392   pic16_aopOp (left,ic,FALSE);
8393   pic16_aopOp (result,ic,TRUE);
8394
8395   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8396
8397   same = pic16_sameRegs(AOP(result),AOP(left));
8398
8399   /* move it to the result */
8400   size = AOP_SIZE(result);    
8401
8402   /* get the msb and put it into the carry */
8403   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8404
8405   offset = 0 ;
8406
8407   while(size--) {
8408
8409     if(same) {
8410       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8411     } else {
8412       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8413       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8414     }
8415
8416     offset++;
8417   }
8418
8419
8420   pic16_freeAsmop(left,NULL,ic,TRUE);
8421   pic16_freeAsmop(result,NULL,ic,TRUE);
8422 }
8423
8424
8425 /* gpasm can get the highest order bit with HIGH/UPPER
8426  * so the following probably is not needed -- VR */
8427  
8428 /*-----------------------------------------------------------------*/
8429 /* genGetHbit - generates code get highest order bit               */
8430 /*-----------------------------------------------------------------*/
8431 static void genGetHbit (iCode *ic)
8432 {
8433     operand *left, *result;
8434     left = IC_LEFT(ic);
8435     result=IC_RESULT(ic);
8436     pic16_aopOp (left,ic,FALSE);
8437     pic16_aopOp (result,ic,FALSE);
8438
8439     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8440     /* get the highest order byte into a */
8441     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8442     if(AOP_TYPE(result) == AOP_CRY){
8443         pic16_emitcode("rlc","a");
8444         pic16_outBitC(result);
8445     }
8446     else{
8447         pic16_emitcode("rl","a");
8448         pic16_emitcode("anl","a,#0x01");
8449         pic16_outAcc(result);
8450     }
8451
8452
8453     pic16_freeAsmop(left,NULL,ic,TRUE);
8454     pic16_freeAsmop(result,NULL,ic,TRUE);
8455 }
8456
8457 #if 0
8458 /*-----------------------------------------------------------------*/
8459 /* AccRol - rotate left accumulator by known count                 */
8460 /*-----------------------------------------------------------------*/
8461 static void AccRol (int shCount)
8462 {
8463     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8464     shCount &= 0x0007;              // shCount : 0..7
8465     switch(shCount){
8466         case 0 :
8467             break;
8468         case 1 :
8469             pic16_emitcode("rl","a");
8470             break;
8471         case 2 :
8472             pic16_emitcode("rl","a");
8473             pic16_emitcode("rl","a");
8474             break;
8475         case 3 :
8476             pic16_emitcode("swap","a");
8477             pic16_emitcode("rr","a");
8478             break;
8479         case 4 :
8480             pic16_emitcode("swap","a");
8481             break;
8482         case 5 :
8483             pic16_emitcode("swap","a");
8484             pic16_emitcode("rl","a");
8485             break;
8486         case 6 :
8487             pic16_emitcode("rr","a");
8488             pic16_emitcode("rr","a");
8489             break;
8490         case 7 :
8491             pic16_emitcode("rr","a");
8492             break;
8493     }
8494 }
8495 #endif
8496
8497 /*-----------------------------------------------------------------*/
8498 /* AccLsh - left shift accumulator by known count                  */
8499 /*-----------------------------------------------------------------*/
8500 static void AccLsh (int shCount)
8501 {
8502         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8503         switch(shCount){
8504                 case 0 :
8505                         return;
8506                         break;
8507                 case 1 :
8508                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8509                         break;
8510                 case 2 :
8511                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         break;
8514                 case 3 :
8515                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         break;
8518                 case 4 :
8519                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8520                         break;
8521                 case 5 :
8522                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8523                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         break;
8525                 case 6 :
8526                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         break;
8529                 case 7 :
8530                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531                         break;
8532         }
8533
8534         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8535 }
8536
8537 /*-----------------------------------------------------------------*/
8538 /* AccRsh - right shift accumulator by known count                 */
8539 /*-----------------------------------------------------------------*/
8540 static void AccRsh (int shCount, int andmask)
8541 {
8542         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8543         switch(shCount){
8544                 case 0 :
8545                         return; break;
8546                 case 1 :
8547                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8548                         break;
8549                 case 2 :
8550                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         break;
8553                 case 3 :
8554                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8555                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         break;
8557                 case 4 :
8558                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8559                         break;
8560                 case 5 :
8561                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         break;
8564                 case 6 :
8565                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         break;
8568                 case 7 :
8569                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570                         break;
8571         }
8572         
8573         if(andmask)
8574                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8575         else
8576                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8577 }
8578
8579 #if 0
8580 /*-----------------------------------------------------------------*/
8581 /* AccSRsh - signed right shift accumulator by known count                 */
8582 /*-----------------------------------------------------------------*/
8583 static void AccSRsh (int shCount)
8584 {
8585     symbol *tlbl ;
8586     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8587     if(shCount != 0){
8588         if(shCount == 1){
8589             pic16_emitcode("mov","c,acc.7");
8590             pic16_emitcode("rrc","a");
8591         } else if(shCount == 2){
8592             pic16_emitcode("mov","c,acc.7");
8593             pic16_emitcode("rrc","a");
8594             pic16_emitcode("mov","c,acc.7");
8595             pic16_emitcode("rrc","a");
8596         } else {
8597             tlbl = newiTempLabel(NULL);
8598             /* rotate right accumulator */
8599             AccRol(8 - shCount);
8600             /* and kill the higher order bits */
8601             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8602             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8603             pic16_emitcode("orl","a,#0x%02x",
8604                      (unsigned char)~SRMask[shCount]);
8605             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8606         }
8607     }
8608 }
8609 #endif
8610
8611 /*-----------------------------------------------------------------*/
8612 /* shiftR1Left2Result - shift right one byte from left to result   */
8613 /*-----------------------------------------------------------------*/
8614 static void shiftR1Left2ResultSigned (operand *left, int offl,
8615                                 operand *result, int offr,
8616                                 int shCount)
8617 {
8618   int same;
8619
8620   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8621
8622   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8623
8624   switch(shCount) {
8625   case 1:
8626     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8627     if(same) 
8628       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8629     else {
8630       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8631       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8632     }
8633
8634     break;
8635   case 2:
8636
8637     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8638     if(same) 
8639       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8640     else {
8641       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8642       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8643     }
8644     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8645     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8646
8647     break;
8648
8649   case 3:
8650     if(same)
8651       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8652     else {
8653       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8654       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8655     }
8656
8657     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8658     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8659     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8660
8661     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8662     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8663
8664     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8665     break;
8666
8667   case 4:
8668     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8669     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8670     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8671     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8672     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8673     break;
8674   case 5:
8675     if(same) {
8676       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8677     } else {
8678       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8679       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8680     }
8681     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8682     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8683     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8684     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8685     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8686     break;
8687
8688   case 6:
8689     if(same) {
8690       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8691       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8692       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8693       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8694       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8695       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8696     } else {
8697       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8698       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8699       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8700       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8701       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8702     }
8703     break;
8704
8705   case 7:
8706     if(same) {
8707       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8708       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8709       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8710       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711     } else {
8712       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8713       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8714       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8715     }
8716
8717   default:
8718     break;
8719   }
8720 }
8721
8722 /*-----------------------------------------------------------------*/
8723 /* shiftR1Left2Result - shift right one byte from left to result   */
8724 /*-----------------------------------------------------------------*/
8725 static void shiftR1Left2Result (operand *left, int offl,
8726                                 operand *result, int offr,
8727                                 int shCount, int sign)
8728 {
8729   int same;
8730
8731   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8732
8733   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8734
8735   /* Copy the msb into the carry if signed. */
8736   if(sign) {
8737     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8738     return;
8739   }
8740
8741
8742
8743   switch(shCount) {
8744   case 1:
8745     emitCLRC;
8746     if(same) 
8747       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8748     else {
8749       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8750       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8751     }
8752     break;
8753   case 2:
8754     emitCLRC;
8755     if(same) {
8756       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8757     } else {
8758       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8759       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8760     }
8761     emitCLRC;
8762     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8763
8764     break;
8765   case 3:
8766     if(same)
8767       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8768     else {
8769       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8770       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8771     }
8772
8773     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8774     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8775     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8776     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8777     break;
8778       
8779   case 4:
8780     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8781     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8782     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783     break;
8784
8785   case 5:
8786     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8787     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8788     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8789     //emitCLRC;
8790     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8791
8792     break;
8793   case 6:
8794
8795     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8796     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8797     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8798     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8799     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8800     break;
8801
8802   case 7:
8803
8804     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8805     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8806     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8807
8808     break;
8809
8810   default:
8811     break;
8812   }
8813 }
8814
8815 /*-----------------------------------------------------------------*/
8816 /* shiftL1Left2Result - shift left one byte from left to result    */
8817 /*-----------------------------------------------------------------*/
8818 static void shiftL1Left2Result (operand *left, int offl,
8819                                 operand *result, int offr, int shCount)
8820 {
8821   int same;
8822
8823   //    char *l;
8824   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825
8826   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8827   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8828     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8829     //    MOVA(l);
8830     /* shift left accumulator */
8831     //AccLsh(shCount); // don't comment out just yet...
8832   //    pic16_aopPut(AOP(result),"a",offr);
8833
8834   switch(shCount) {
8835   case 1:
8836     /* Shift left 1 bit position */
8837     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8838     if(same) {
8839       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8840     } else {
8841       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8842       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8843     }
8844     break;
8845   case 2:
8846     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8847     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8848     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8849     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8850     break;
8851   case 3:
8852     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8853     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8854     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8855     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8856     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8857     break;
8858   case 4:
8859     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8860     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8861     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8862     break;
8863   case 5:
8864     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8865     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8866     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8867     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8868     break;
8869   case 6:
8870     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8871     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8872     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8873     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8874     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8875     break;
8876   case 7:
8877     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8878     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8879     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8880     break;
8881
8882   default:
8883     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8884   }
8885
8886 }
8887
8888 /*-----------------------------------------------------------------*/
8889 /* movLeft2Result - move byte from left to result                  */
8890 /*-----------------------------------------------------------------*/
8891 static void movLeft2Result (operand *left, int offl,
8892                             operand *result, int offr)
8893 {
8894   char *l;
8895   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8896   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8897     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8898
8899     if (*l == '@' && (IS_AOP_PREG(result))) {
8900       pic16_emitcode("mov","a,%s",l);
8901       pic16_aopPut(AOP(result),"a",offr);
8902     } else {
8903       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8904       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8905     }
8906   }
8907 }
8908
8909 /*-----------------------------------------------------------------*/
8910 /* shiftL2Left2Result - shift left two bytes from left to result   */
8911 /*-----------------------------------------------------------------*/
8912 static void shiftL2Left2Result (operand *left, int offl,
8913                                 operand *result, int offr, int shCount)
8914 {
8915   int same = pic16_sameRegs(AOP(result), AOP(left));
8916   int i;
8917
8918   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8919
8920   if (same && (offl != offr)) { // shift bytes
8921     if (offr > offl) {
8922        for(i=1;i>-1;i--) {
8923          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8924          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8925        }
8926     } else { // just treat as different later on
8927                 same = 0;
8928     }
8929   }
8930
8931   if(same) {
8932     switch(shCount) {
8933     case 0:
8934       break;
8935     case 1:
8936     case 2:
8937     case 3:
8938
8939       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8940       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8941       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8942
8943       while(--shCount) {
8944                 emitCLRC;
8945                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8946                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8947       }
8948
8949       break;
8950     case 4:
8951     case 5:
8952       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8953       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8954       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8955       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8956       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8957       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8958       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8959       if(shCount >=5) {
8960                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8961                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8962       }
8963       break;
8964     case 6:
8965       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8968       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8969       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8970       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8971       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8975       break;
8976     case 7:
8977       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8980       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8981       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8982     }
8983
8984   } else {
8985     switch(shCount) {
8986     case 0:
8987       break;
8988     case 1:
8989     case 2:
8990     case 3:
8991       /* note, use a mov/add for the shift since the mov has a
8992          chance of getting optimized out */
8993       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8994       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8995       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8996       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8997       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8998
8999       while(--shCount) {
9000                 emitCLRC;
9001                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9002                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9003       }
9004       break;
9005
9006     case 4:
9007     case 5:
9008       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9009       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9010       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9011       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9012       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9013       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9014       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9015       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9016
9017
9018       if(shCount == 5) {
9019                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9020                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9021       }
9022       break;
9023     case 6:
9024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9025       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9026       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9027       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9028
9029       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9030       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9031       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9032       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9033       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9034       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9037       break;
9038     case 7:
9039       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9041       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9042       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9043       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9044     }
9045   }
9046
9047 }
9048 /*-----------------------------------------------------------------*/
9049 /* shiftR2Left2Result - shift right two bytes from left to result  */
9050 /*-----------------------------------------------------------------*/
9051 static void shiftR2Left2Result (operand *left, int offl,
9052                                 operand *result, int offr,
9053                                 int shCount, int sign)
9054 {
9055   int same = pic16_sameRegs(AOP(result), AOP(left));
9056   int i;
9057   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9058
9059   if (same && (offl != offr)) { // shift right bytes
9060     if (offr < offl) {
9061        for(i=0;i<2;i++) {
9062          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9063          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9064        }
9065     } else { // just treat as different later on
9066                 same = 0;
9067     }
9068   }
9069
9070   switch(shCount) {
9071   case 0:
9072     break;
9073   case 1:
9074   case 2:
9075   case 3:
9076     if(sign)
9077       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9078     else
9079       emitCLRC;
9080
9081     if(same) {
9082       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9083       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9084     } else {
9085       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9086       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9087       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9088       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9089     }
9090
9091     while(--shCount) {
9092       if(sign)
9093                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9094       else
9095                 emitCLRC;
9096       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9098     }
9099     break;
9100   case 4:
9101   case 5:
9102     if(same) {
9103
9104       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9105       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9106       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9107
9108       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9109       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9110       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9112     } else {
9113       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9114       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9115       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9116
9117       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9118       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9119       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9120       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9121       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9122     }
9123
9124     if(shCount >=5) {
9125       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9126       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9127     }
9128
9129     if(sign) {
9130       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9131       pic16_emitpcode(POC_BTFSC, 
9132                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9133       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9134     }
9135
9136     break;
9137
9138   case 6:
9139     if(same) {
9140
9141       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9142       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9143
9144       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9145       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9146       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9147       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9148       if(sign) {
9149         pic16_emitpcode(POC_BTFSC, 
9150                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9151         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9152       }
9153       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9154       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9157     } else {
9158       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9159       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9160       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9161       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9162       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9163       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9164       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9165       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9166       if(sign) {
9167         pic16_emitpcode(POC_BTFSC, 
9168                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9169         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9170       }
9171       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9172       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9173
9174         
9175     }
9176
9177     break;
9178   case 7:
9179     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9180     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9181     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9182     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9183     if(sign) {
9184       emitSKPNC;
9185       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9186     } else 
9187       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9188   }
9189 }
9190
9191
9192 /*-----------------------------------------------------------------*/
9193 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9194 /*-----------------------------------------------------------------*/
9195 static void shiftLLeftOrResult (operand *left, int offl,
9196                                 operand *result, int offr, int shCount)
9197 {
9198     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9199
9200     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9201     /* shift left accumulator */
9202     AccLsh(shCount);
9203     /* or with result */
9204     /* back to result */
9205     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9206 }
9207
9208 /*-----------------------------------------------------------------*/
9209 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9210 /*-----------------------------------------------------------------*/
9211 static void shiftRLeftOrResult (operand *left, int offl,
9212                                 operand *result, int offr, int shCount)
9213 {
9214     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9215     
9216     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9217     /* shift right accumulator */
9218     AccRsh(shCount, 1);
9219     /* or with result */
9220     /* back to result */
9221     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genlshOne - left shift a one byte quantity by known count       */
9226 /*-----------------------------------------------------------------*/
9227 static void genlshOne (operand *result, operand *left, int shCount)
9228 {       
9229     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9230     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9231 }
9232
9233 /*-----------------------------------------------------------------*/
9234 /* genlshTwo - left shift two bytes by known amount != 0           */
9235 /*-----------------------------------------------------------------*/
9236 static void genlshTwo (operand *result,operand *left, int shCount)
9237 {
9238     int size;
9239     
9240     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9241     size = pic16_getDataSize(result);
9242
9243     /* if shCount >= 8 */
9244     if (shCount >= 8) {
9245         shCount -= 8 ;
9246
9247         if (size > 1){
9248             if (shCount)
9249                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9250             else 
9251                 movLeft2Result(left, LSB, result, MSB16);
9252         }
9253         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9254     }
9255
9256     /*  1 <= shCount <= 7 */
9257     else {  
9258         if(size == 1)
9259             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9260         else 
9261             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9262     }
9263 }
9264
9265 /*-----------------------------------------------------------------*/
9266 /* shiftLLong - shift left one long from left to result            */
9267 /* offr = LSB or MSB16                                             */
9268 /*-----------------------------------------------------------------*/
9269 static void shiftLLong (operand *left, operand *result, int offr )
9270 {
9271     int size = AOP_SIZE(result);
9272     int same = pic16_sameRegs(AOP(left),AOP(result));
9273         int i;
9274
9275     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9276
9277         if (same && (offr == MSB16)) { //shift one byte
9278                 for(i=size-1;i>=MSB16;i--) {
9279                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9280                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9281                 }
9282         } else {
9283                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9284         }
9285         
9286     if (size > LSB+offr ){
9287                 if (same) {
9288                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9289                 } else {
9290                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9291                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9292                 }
9293          }
9294
9295     if(size > MSB16+offr){
9296                 if (same) {
9297                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9298                 } else {
9299                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9300                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9301                 }
9302     }
9303
9304     if(size > MSB24+offr){
9305                 if (same) {
9306                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9307                 } else {
9308                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9309                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9310                 }
9311     }
9312
9313     if(size > MSB32+offr){
9314                 if (same) {
9315                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9316                 } else {
9317                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9318                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9319                 }
9320     }
9321     if(offr != LSB)
9322                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9323
9324 }
9325
9326 /*-----------------------------------------------------------------*/
9327 /* genlshFour - shift four byte by a known amount != 0             */
9328 /*-----------------------------------------------------------------*/
9329 static void genlshFour (operand *result, operand *left, int shCount)
9330 {
9331     int size;
9332
9333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9334     size = AOP_SIZE(result);
9335
9336     /* if shifting more that 3 bytes */
9337     if (shCount >= 24 ) {
9338         shCount -= 24;
9339         if (shCount)
9340             /* lowest order of left goes to the highest
9341             order of the destination */
9342             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9343         else
9344             movLeft2Result(left, LSB, result, MSB32);
9345
9346                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9347                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9348                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9349
9350         return;
9351     }
9352
9353     /* more than two bytes */
9354     else if ( shCount >= 16 ) {
9355         /* lower order two bytes goes to higher order two bytes */
9356         shCount -= 16;
9357         /* if some more remaining */
9358         if (shCount)
9359             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9360         else {
9361             movLeft2Result(left, MSB16, result, MSB32);
9362             movLeft2Result(left, LSB, result, MSB24);
9363         }
9364                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9365                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9366         return;
9367     }    
9368
9369     /* if more than 1 byte */
9370     else if ( shCount >= 8 ) {
9371         /* lower order three bytes goes to higher order  three bytes */
9372         shCount -= 8;
9373         if(size == 2){
9374             if(shCount)
9375                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9376             else
9377                 movLeft2Result(left, LSB, result, MSB16);
9378         }
9379         else{   /* size = 4 */
9380             if(shCount == 0){
9381                 movLeft2Result(left, MSB24, result, MSB32);
9382                 movLeft2Result(left, MSB16, result, MSB24);
9383                 movLeft2Result(left, LSB, result, MSB16);
9384                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9385             }
9386             else if(shCount == 1)
9387                 shiftLLong(left, result, MSB16);
9388             else{
9389                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9390                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9391                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9392                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9393             }
9394         }
9395     }
9396
9397     /* 1 <= shCount <= 7 */
9398     else if(shCount <= 3)
9399     { 
9400         shiftLLong(left, result, LSB);
9401         while(--shCount >= 1)
9402             shiftLLong(result, result, LSB);
9403     }
9404     /* 3 <= shCount <= 7, optimize */
9405     else{
9406         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9407         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9408         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9409     }
9410 }
9411
9412 /*-----------------------------------------------------------------*/
9413 /* genLeftShiftLiteral - left shifting by known count              */
9414 /*-----------------------------------------------------------------*/
9415 void pic16_genLeftShiftLiteral (operand *left,
9416                                  operand *right,
9417                                  operand *result,
9418                                  iCode *ic)
9419 {    
9420     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9421     int size;
9422
9423     FENTRY;
9424     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9425     pic16_freeAsmop(right,NULL,ic,TRUE);
9426
9427     pic16_aopOp(left,ic,FALSE);
9428     pic16_aopOp(result,ic,TRUE);
9429
9430     size = getSize(operandType(result));
9431
9432 #if VIEW_SIZE
9433     pic16_emitcode("; shift left ","result %d, left %d",size,
9434              AOP_SIZE(left));
9435 #endif
9436
9437     /* I suppose that the left size >= result size */
9438     if(shCount == 0){
9439         while(size--){
9440             movLeft2Result(left, size, result, size);
9441         }
9442     }
9443
9444     else if(shCount >= (size * 8))
9445         while(size--)
9446             pic16_aopPut(AOP(result),zero,size);
9447     else{
9448         switch (size) {
9449             case 1:
9450                 genlshOne (result,left,shCount);
9451                 break;
9452
9453             case 2:
9454             case 3:
9455                 genlshTwo (result,left,shCount);
9456                 break;
9457
9458             case 4:
9459                 genlshFour (result,left,shCount);
9460                 break;
9461         }
9462     }
9463     pic16_freeAsmop(left,NULL,ic,TRUE);
9464     pic16_freeAsmop(result,NULL,ic,TRUE);
9465 }
9466
9467 /*-----------------------------------------------------------------*
9468  * genMultiAsm - repeat assembly instruction for size of register.
9469  * if endian == 1, then the high byte (i.e base address + size of 
9470  * register) is used first else the low byte is used first;
9471  *-----------------------------------------------------------------*/
9472 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9473 {
9474
9475   int offset = 0;
9476
9477   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9478
9479   if(!reg)
9480     return;
9481
9482   if(!endian) {
9483     endian = 1;
9484   } else {
9485     endian = -1;
9486     offset = size-1;
9487   }
9488
9489   while(size--) {
9490     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9491     offset += endian;
9492   }
9493
9494 }
9495
9496 #if !(USE_GENERIC_SIGNED_SHIFT)
9497 /*-----------------------------------------------------------------*/
9498 /* genLeftShift - generates code for left shifting                 */
9499 /*-----------------------------------------------------------------*/
9500 static void genLeftShift (iCode *ic)
9501 {
9502   operand *left,*right, *result;
9503   int size, offset;
9504 //  char *l;
9505   symbol *tlbl , *tlbl1;
9506   pCodeOp *pctemp;
9507
9508   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9509
9510   right = IC_RIGHT(ic);
9511   left  = IC_LEFT(ic);
9512   result = IC_RESULT(ic);
9513
9514   pic16_aopOp(right,ic,FALSE);
9515
9516   /* if the shift count is known then do it 
9517      as efficiently as possible */
9518   if (AOP_TYPE(right) == AOP_LIT) {
9519     pic16_genLeftShiftLiteral (left,right,result,ic);
9520     return ;
9521   }
9522
9523   /* shift count is unknown then we have to form
9524    * a loop. Get the loop count in WREG : Note: we take
9525    * only the lower order byte since shifting
9526    * more than 32 bits make no sense anyway, ( the
9527    * largest size of an object can be only 32 bits ) */
9528   
9529   pic16_aopOp(left,ic,FALSE);
9530   pic16_aopOp(result,ic,FALSE);
9531
9532   /* now move the left to the result if they are not the
9533    * same, and if size > 1,
9534    * and if right is not same to result (!!!) -- VR */
9535   if (!pic16_sameRegs(AOP(left),AOP(result))
9536       && (AOP_SIZE(result) > 1)) {
9537
9538     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9539
9540     size = AOP_SIZE(result);
9541     offset=0;
9542     while (size--) {
9543
9544 #if 0
9545       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9546       if (*l == '@' && (IS_AOP_PREG(result))) {
9547
9548           pic16_emitcode("mov","a,%s",l);
9549           pic16_aopPut(AOP(result),"a",offset);
9550       } else
9551 #endif
9552       {
9553         /* we don't know if left is a literal or a register, take care -- VR */
9554         pic16_mov2f(AOP(result), AOP(left), offset);
9555       }
9556       offset++;
9557     }
9558   }
9559
9560   size = AOP_SIZE(result);
9561
9562   /* if it is only one byte then */
9563   if (size == 1) {
9564     if(optimized_for_speed) {
9565       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9566       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9567       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9568       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9569       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9570       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9571       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9572       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9573       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9574       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9575       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9576       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9577     } else {
9578
9579       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9580
9581       tlbl = newiTempLabel(NULL);
9582
9583 #if 1
9584       /* this is already done, why change it? */
9585       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9586                 pic16_mov2f(AOP(result), AOP(left), 0);
9587       }
9588 #endif
9589
9590       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9591       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9592       pic16_emitpLabel(tlbl->key);
9593       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9594       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9595       emitSKPC;
9596       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9597     }
9598     goto release ;
9599   }
9600     
9601   if (pic16_sameRegs(AOP(left),AOP(result))) {
9602
9603     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9604     
9605     tlbl = newiTempLabel(NULL);
9606     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9607     genMultiAsm(POC_RRCF, result, size,1);
9608     pic16_emitpLabel(tlbl->key);
9609     genMultiAsm(POC_RLCF, result, size,0);
9610     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9611     emitSKPC;
9612     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9613     goto release;
9614   }
9615
9616   //tlbl = newiTempLabel(NULL);
9617   //offset = 0 ;   
9618   //tlbl1 = newiTempLabel(NULL);
9619
9620   //reAdjustPreg(AOP(result));    
9621     
9622   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9623   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9624   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9625   //MOVA(l);
9626   //pic16_emitcode("add","a,acc");         
9627   //pic16_aopPut(AOP(result),"a",offset++);
9628   //while (--size) {
9629   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9630   //  MOVA(l);
9631   //  pic16_emitcode("rlc","a");         
9632   //  pic16_aopPut(AOP(result),"a",offset++);
9633   //}
9634   //reAdjustPreg(AOP(result));
9635
9636   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9637   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9638
9639
9640   tlbl = newiTempLabel(NULL);
9641   tlbl1= newiTempLabel(NULL);
9642
9643   size = AOP_SIZE(result);
9644   offset = 1;
9645
9646   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9647
9648   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9649
9650   /* offset should be 0, 1 or 3 */
9651   
9652   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9653   emitSKPNZ;
9654   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9655
9656   pic16_emitpcode(POC_MOVWF, pctemp);
9657
9658
9659   pic16_emitpLabel(tlbl->key);
9660
9661   emitCLRC;
9662   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9663   while(--size)
9664     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9665
9666   pic16_emitpcode(POC_DECFSZ,  pctemp);
9667   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9668   pic16_emitpLabel(tlbl1->key);
9669
9670   pic16_popReleaseTempReg(pctemp,1);
9671
9672
9673  release:
9674   pic16_freeAsmop (right,NULL,ic,TRUE);
9675   pic16_freeAsmop(left,NULL,ic,TRUE);
9676   pic16_freeAsmop(result,NULL,ic,TRUE);
9677 }
9678 #endif
9679
9680
9681 #if 0
9682 #error old code (left here for reference)
9683 /*-----------------------------------------------------------------*/
9684 /* genLeftShift - generates code for left shifting                 */
9685 /*-----------------------------------------------------------------*/
9686 static void genLeftShift (iCode *ic)
9687 {
9688   operand *left,*right, *result;
9689   int size, offset;
9690   char *l;
9691   symbol *tlbl , *tlbl1;
9692   pCodeOp *pctemp;
9693
9694   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9695
9696   right = IC_RIGHT(ic);
9697   left  = IC_LEFT(ic);
9698   result = IC_RESULT(ic);
9699
9700   pic16_aopOp(right,ic,FALSE);
9701
9702   /* if the shift count is known then do it 
9703      as efficiently as possible */
9704   if (AOP_TYPE(right) == AOP_LIT) {
9705     pic16_genLeftShiftLiteral (left,right,result,ic);
9706     return ;
9707   }
9708
9709   /* shift count is unknown then we have to form 
9710      a loop get the loop count in B : Note: we take
9711      only the lower order byte since shifting
9712      more that 32 bits make no sense anyway, ( the
9713      largest size of an object can be only 32 bits ) */  
9714
9715     
9716   pic16_aopOp(left,ic,FALSE);
9717   pic16_aopOp(result,ic,FALSE);
9718
9719   /* now move the left to the result if they are not the
9720      same */
9721   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9722       AOP_SIZE(result) > 1) {
9723
9724     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9725
9726     size = AOP_SIZE(result);
9727     offset=0;
9728     while (size--) {
9729       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9730       if (*l == '@' && (IS_AOP_PREG(result))) {
9731
9732         pic16_emitcode("mov","a,%s",l);
9733         pic16_aopPut(AOP(result),"a",offset);
9734       } else {
9735
9736         /* we don't know if left is a literal or a register, take care -- VR */
9737         pic16_mov2f(AOP(result), AOP(left), offset);
9738       }
9739       offset++;
9740     }
9741   }
9742
9743   size = AOP_SIZE(result);
9744
9745   /* if it is only one byte then */
9746   if (size == 1) {
9747     if(optimized_for_speed) {
9748       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9749       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9750       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9751       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9752       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9753       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9754       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9755       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9756       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9757       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9758       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9759       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9760     } else {
9761
9762       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9763
9764       tlbl = newiTempLabel(NULL);
9765       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9766                 pic16_mov2f(AOP(result), AOP(left), 0);
9767                 
9768 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9769 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9770       }
9771
9772       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9773       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9774       pic16_emitpLabel(tlbl->key);
9775       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9776       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9777       emitSKPC;
9778       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9779     }
9780     goto release ;
9781   }
9782     
9783   if (pic16_sameRegs(AOP(left),AOP(result))) {
9784
9785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9786     
9787     tlbl = newiTempLabel(NULL);
9788     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9789     genMultiAsm(POC_RRCF, result, size,1);
9790     pic16_emitpLabel(tlbl->key);
9791     genMultiAsm(POC_RLCF, result, size,0);
9792     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9793     emitSKPC;
9794     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9795     goto release;
9796   }
9797
9798   //tlbl = newiTempLabel(NULL);
9799   //offset = 0 ;   
9800   //tlbl1 = newiTempLabel(NULL);
9801
9802   //reAdjustPreg(AOP(result));    
9803     
9804   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9805   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9806   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9807   //MOVA(l);
9808   //pic16_emitcode("add","a,acc");         
9809   //pic16_aopPut(AOP(result),"a",offset++);
9810   //while (--size) {
9811   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9812   //  MOVA(l);
9813   //  pic16_emitcode("rlc","a");         
9814   //  pic16_aopPut(AOP(result),"a",offset++);
9815   //}
9816   //reAdjustPreg(AOP(result));
9817
9818   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9819   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9820
9821
9822   tlbl = newiTempLabel(NULL);
9823   tlbl1= newiTempLabel(NULL);
9824
9825   size = AOP_SIZE(result);
9826   offset = 1;
9827
9828   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9829
9830   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9831
9832   /* offset should be 0, 1 or 3 */
9833   
9834   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9835   emitSKPNZ;
9836   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9837
9838   pic16_emitpcode(POC_MOVWF, pctemp);
9839
9840
9841   pic16_emitpLabel(tlbl->key);
9842
9843   emitCLRC;
9844   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9845   while(--size)
9846     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9847
9848   pic16_emitpcode(POC_DECFSZ,  pctemp);
9849   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9850   pic16_emitpLabel(tlbl1->key);
9851
9852   pic16_popReleaseTempReg(pctemp,1);
9853
9854
9855  release:
9856   pic16_freeAsmop (right,NULL,ic,TRUE);
9857   pic16_freeAsmop(left,NULL,ic,TRUE);
9858   pic16_freeAsmop(result,NULL,ic,TRUE);
9859 }
9860 #endif
9861
9862 /*-----------------------------------------------------------------*/
9863 /* genrshOne - right shift a one byte quantity by known count      */
9864 /*-----------------------------------------------------------------*/
9865 static void genrshOne (operand *result, operand *left,
9866                        int shCount, int sign)
9867 {
9868     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9869     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9870 }
9871
9872 /*-----------------------------------------------------------------*/
9873 /* genrshTwo - right shift two bytes by known amount != 0          */
9874 /*-----------------------------------------------------------------*/
9875 static void genrshTwo (operand *result,operand *left,
9876                        int shCount, int sign)
9877 {
9878   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9879   /* if shCount >= 8 */
9880   if (shCount >= 8) {
9881     shCount -= 8 ;
9882     if (shCount)
9883       shiftR1Left2Result(left, MSB16, result, LSB,
9884                          shCount, sign);
9885     else
9886       movLeft2Result(left, MSB16, result, LSB);
9887
9888     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9889
9890     if(sign) {
9891       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9892       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),MSB16));
9893     }
9894   }
9895
9896   /*  1 <= shCount <= 7 */
9897   else
9898     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9899 }
9900
9901 /*-----------------------------------------------------------------*/
9902 /* shiftRLong - shift right one long from left to result           */
9903 /* offl = LSB or MSB16                                             */
9904 /*-----------------------------------------------------------------*/
9905 static void shiftRLong (operand *left, int offl,
9906                         operand *result, int sign)
9907 {
9908     int size = AOP_SIZE(result);
9909     int same = pic16_sameRegs(AOP(left),AOP(result));
9910     int i;
9911     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9912
9913         if (same && (offl == MSB16)) { //shift one byte right
9914                 for(i=MSB16;i<size;i++) {
9915                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9916                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9917                 }
9918         }
9919
9920     if(sign)
9921                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9922         else
9923                 emitCLRC;
9924
9925         if (same) {
9926                 if (offl == LSB)
9927                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9928         } else {
9929         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9930         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9931         }
9932
9933     if(offl == MSB16) {
9934         /* add sign of "a" */
9935         pic16_addSign(result, MSB32, sign);
9936         }
9937
9938         if (same) {
9939         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9940         } else {
9941         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9942         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9943         }
9944         
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9947         } else {
9948         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9949         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9950         }
9951
9952         if (same) {
9953         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9954         } else {
9955         if(offl == LSB){
9956                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9957                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9958         }
9959         }
9960 }
9961
9962 /*-----------------------------------------------------------------*/
9963 /* genrshFour - shift four byte by a known amount != 0             */
9964 /*-----------------------------------------------------------------*/
9965 static void genrshFour (operand *result, operand *left,
9966                         int shCount, int sign)
9967 {
9968   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9969   /* if shifting more that 3 bytes */
9970   if(shCount >= 24 ) {
9971     shCount -= 24;
9972     if(shCount)
9973       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9974     else
9975       movLeft2Result(left, MSB32, result, LSB);
9976
9977     pic16_addSign(result, MSB16, sign);
9978   }
9979   else if(shCount >= 16){
9980     shCount -= 16;
9981     if(shCount)
9982       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9983     else{
9984       movLeft2Result(left, MSB24, result, LSB);
9985       movLeft2Result(left, MSB32, result, MSB16);
9986     }
9987     pic16_addSign(result, MSB24, sign);
9988   }
9989   else if(shCount >= 8){
9990     shCount -= 8;
9991     if(shCount == 1)
9992       shiftRLong(left, MSB16, result, sign);
9993     else if(shCount == 0){
9994       movLeft2Result(left, MSB16, result, LSB);
9995       movLeft2Result(left, MSB24, result, MSB16);
9996       movLeft2Result(left, MSB32, result, MSB24);
9997       pic16_addSign(result, MSB32, sign);
9998     }
9999     else{ //shcount >= 2
10000       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10001       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10002       /* the last shift is signed */
10003       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10004       pic16_addSign(result, MSB32, sign);
10005     }
10006   }
10007   else{   /* 1 <= shCount <= 7 */
10008     if(shCount <= 2){
10009       shiftRLong(left, LSB, result, sign);
10010       if(shCount == 2)
10011         shiftRLong(result, LSB, result, sign);
10012     }
10013     else{
10014       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10015       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10016       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10017     }
10018   }
10019 }
10020
10021 /*-----------------------------------------------------------------*/
10022 /* genRightShiftLiteral - right shifting by known count            */
10023 /*-----------------------------------------------------------------*/
10024 static void genRightShiftLiteral (operand *left,
10025                                   operand *right,
10026                                   operand *result,
10027                                   iCode *ic,
10028                                   int sign)
10029 {    
10030   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10031   int lsize,res_size;
10032
10033   pic16_freeAsmop(right,NULL,ic,TRUE);
10034
10035   pic16_aopOp(left,ic,FALSE);
10036   pic16_aopOp(result,ic,TRUE);
10037
10038   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10039
10040 #if VIEW_SIZE
10041   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10042                  AOP_SIZE(left));
10043 #endif
10044
10045   lsize = pic16_getDataSize(left);
10046   res_size = pic16_getDataSize(result);
10047   /* test the LEFT size !!! */
10048
10049   /* I suppose that the left size >= result size */
10050   if(shCount == 0){
10051     assert (res_size <= lsize);
10052     while (res_size--) {
10053       pic16_mov2f (AOP(result), AOP(left), res_size);
10054     } // for
10055   }
10056
10057   else if(shCount >= (lsize * 8)){
10058
10059     if(res_size == 1) {
10060       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10061       if(sign) {
10062         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10064       }
10065     } else {
10066
10067       if(sign) {
10068         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10069         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10071         while(res_size--)
10072           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10073
10074       } else {
10075
10076         while(res_size--)
10077           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10078       }
10079     }
10080   } else {
10081
10082     switch (res_size) {
10083     case 1:
10084       genrshOne (result,left,shCount,sign);
10085       break;
10086
10087     case 2:
10088       genrshTwo (result,left,shCount,sign);
10089       break;
10090
10091     case 4:
10092       genrshFour (result,left,shCount,sign);
10093       break;
10094     default :
10095       break;
10096     }
10097
10098   }
10099
10100   pic16_freeAsmop(left,NULL,ic,TRUE);
10101   pic16_freeAsmop(result,NULL,ic,TRUE);
10102 }
10103
10104 #if !(USE_GENERIC_SIGNED_SHIFT)
10105 /*-----------------------------------------------------------------*/
10106 /* genSignedRightShift - right shift of signed number              */
10107 /*-----------------------------------------------------------------*/
10108 static void genSignedRightShift (iCode *ic)
10109 {
10110   operand *right, *left, *result;
10111   int size, offset;
10112   //  char *l;
10113   symbol *tlbl, *tlbl1 ;
10114   pCodeOp *pctemp;
10115
10116   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10117
10118   /* we do it the hard way put the shift count in b
10119      and loop thru preserving the sign */
10120   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10121
10122   right = IC_RIGHT(ic);
10123   left  = IC_LEFT(ic);
10124   result = IC_RESULT(ic);
10125
10126   pic16_aopOp(right,ic,FALSE);  
10127   pic16_aopOp(left,ic,FALSE);
10128   pic16_aopOp(result,ic,FALSE);
10129
10130
10131   if ( AOP_TYPE(right) == AOP_LIT) {
10132     genRightShiftLiteral (left,right,result,ic,1);
10133     return ;
10134   }
10135   /* shift count is unknown then we have to form 
10136      a loop get the loop count in B : Note: we take
10137      only the lower order byte since shifting
10138      more that 32 bits make no sense anyway, ( the
10139      largest size of an object can be only 32 bits ) */  
10140
10141   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10142   //pic16_emitcode("inc","b");
10143   //pic16_freeAsmop (right,NULL,ic,TRUE);
10144   //pic16_aopOp(left,ic,FALSE);
10145   //pic16_aopOp(result,ic,FALSE);
10146
10147   /* now move the left to the result if they are not the
10148      same */
10149   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10150       AOP_SIZE(result) > 1) {
10151
10152     size = AOP_SIZE(result);
10153     offset=0;
10154     while (size--) { 
10155       /*
10156         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10157         if (*l == '@' && IS_AOP_PREG(result)) {
10158
10159         pic16_emitcode("mov","a,%s",l);
10160         pic16_aopPut(AOP(result),"a",offset);
10161         } else
10162         pic16_aopPut(AOP(result),l,offset);
10163       */
10164       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10165       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10166
10167       offset++;
10168     }
10169   }
10170
10171   /* mov the highest order bit to OVR */    
10172   tlbl = newiTempLabel(NULL);
10173   tlbl1= newiTempLabel(NULL);
10174
10175   size = AOP_SIZE(result);
10176   offset = size - 1;
10177
10178   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10179
10180   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10181
10182   /* offset should be 0, 1 or 3 */
10183   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10184   emitSKPNZ;
10185   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10186
10187   pic16_emitpcode(POC_MOVWF, pctemp);
10188
10189
10190   pic16_emitpLabel(tlbl->key);
10191
10192   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10193   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10194
10195   while(--size) {
10196     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10197   }
10198
10199   pic16_emitpcode(POC_DECFSZ,  pctemp);
10200   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10201   pic16_emitpLabel(tlbl1->key);
10202
10203   pic16_popReleaseTempReg(pctemp,1);
10204 #if 0
10205   size = AOP_SIZE(result);
10206   offset = size - 1;
10207   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10208   pic16_emitcode("rlc","a");
10209   pic16_emitcode("mov","ov,c");
10210   /* if it is only one byte then */
10211   if (size == 1) {
10212     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10213     MOVA(l);
10214     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10215     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10216     pic16_emitcode("mov","c,ov");
10217     pic16_emitcode("rrc","a");
10218     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10219     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10220     pic16_aopPut(AOP(result),"a",0);
10221     goto release ;
10222   }
10223
10224   reAdjustPreg(AOP(result));
10225   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10227   pic16_emitcode("mov","c,ov");
10228   while (size--) {
10229     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10230     MOVA(l);
10231     pic16_emitcode("rrc","a");         
10232     pic16_aopPut(AOP(result),"a",offset--);
10233   }
10234   reAdjustPreg(AOP(result));
10235   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10237
10238  release:
10239 #endif
10240
10241   pic16_freeAsmop(left,NULL,ic,TRUE);
10242   pic16_freeAsmop(result,NULL,ic,TRUE);
10243   pic16_freeAsmop(right,NULL,ic,TRUE);
10244 }
10245 #endif
10246
10247 #if !(USE_GENERIC_SIGNED_SHIFT)
10248 #warning This implementation of genRightShift() is incomplete!
10249 /*-----------------------------------------------------------------*/
10250 /* genRightShift - generate code for right shifting                */
10251 /*-----------------------------------------------------------------*/
10252 static void genRightShift (iCode *ic)
10253 {
10254     operand *right, *left, *result;
10255     sym_link *letype ;
10256     int size, offset;
10257     char *l;
10258     symbol *tlbl, *tlbl1 ;
10259
10260     /* if signed then we do it the hard way preserve the
10261     sign bit moving it inwards */
10262     letype = getSpec(operandType(IC_LEFT(ic)));
10263     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10264
10265     if (!SPEC_USIGN(letype)) {
10266         genSignedRightShift (ic);
10267         return ;
10268     }
10269
10270     /* signed & unsigned types are treated the same : i.e. the
10271     signed is NOT propagated inwards : quoting from the
10272     ANSI - standard : "for E1 >> E2, is equivalent to division
10273     by 2**E2 if unsigned or if it has a non-negative value,
10274     otherwise the result is implementation defined ", MY definition
10275     is that the sign does not get propagated */
10276
10277     right = IC_RIGHT(ic);
10278     left  = IC_LEFT(ic);
10279     result = IC_RESULT(ic);
10280
10281     pic16_aopOp(right,ic,FALSE);
10282
10283     /* if the shift count is known then do it 
10284     as efficiently as possible */
10285     if (AOP_TYPE(right) == AOP_LIT) {
10286         genRightShiftLiteral (left,right,result,ic, 0);
10287         return ;
10288     }
10289
10290     /* shift count is unknown then we have to form 
10291     a loop get the loop count in B : Note: we take
10292     only the lower order byte since shifting
10293     more that 32 bits make no sense anyway, ( the
10294     largest size of an object can be only 32 bits ) */  
10295
10296     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10297     pic16_emitcode("inc","b");
10298     pic16_aopOp(left,ic,FALSE);
10299     pic16_aopOp(result,ic,FALSE);
10300
10301     /* now move the left to the result if they are not the
10302     same */
10303     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10304         AOP_SIZE(result) > 1) {
10305
10306         size = AOP_SIZE(result);
10307         offset=0;
10308         while (size--) {
10309             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10310             if (*l == '@' && IS_AOP_PREG(result)) {
10311
10312                 pic16_emitcode("mov","a,%s",l);
10313                 pic16_aopPut(AOP(result),"a",offset);
10314             } else
10315                 pic16_aopPut(AOP(result),l,offset);
10316             offset++;
10317         }
10318     }
10319
10320     tlbl = newiTempLabel(NULL);
10321     tlbl1= newiTempLabel(NULL);
10322     size = AOP_SIZE(result);
10323     offset = size - 1;
10324
10325     /* if it is only one byte then */
10326     if (size == 1) {
10327
10328       tlbl = newiTempLabel(NULL);
10329       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10330         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10331         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10332       }
10333
10334       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10335       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10336       pic16_emitpLabel(tlbl->key);
10337       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10338       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10339       emitSKPC;
10340       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10341
10342       goto release ;
10343     }
10344
10345     reAdjustPreg(AOP(result));
10346     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10347     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10348     CLRC;
10349     while (size--) {
10350         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10351         MOVA(l);
10352         pic16_emitcode("rrc","a");         
10353         pic16_aopPut(AOP(result),"a",offset--);
10354     }
10355     reAdjustPreg(AOP(result));
10356
10357     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10358     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10359
10360 release:
10361     pic16_freeAsmop(left,NULL,ic,TRUE);
10362     pic16_freeAsmop (right,NULL,ic,TRUE);
10363     pic16_freeAsmop(result,NULL,ic,TRUE);
10364 }
10365 #endif
10366
10367 #if (USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genGenericShift - generates code for left or right shifting     */
10370 /*-----------------------------------------------------------------*/
10371 static void genGenericShift (iCode *ic, int isShiftLeft) {
10372   operand *left,*right, *result;
10373   int offset;
10374   int sign, signedCount;
10375   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10376   PIC_OPCODE pos_shift, neg_shift;
10377
10378   FENTRY;
10379
10380   right = IC_RIGHT(ic);
10381   left  = IC_LEFT(ic);
10382   result = IC_RESULT(ic);
10383
10384   pic16_aopOp(right,ic,FALSE);
10385   pic16_aopOp(left,ic,FALSE);
10386   pic16_aopOp(result,ic,TRUE);
10387
10388   sign = !SPEC_USIGN(operandType (left));
10389   signedCount = !SPEC_USIGN(operandType (right));
10390
10391   /* if the shift count is known then do it 
10392      as efficiently as possible */
10393   if (AOP_TYPE(right) == AOP_LIT) {
10394     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10395     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10396     // we should modify right->aopu.aop_lit here!
10397     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10398     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10399     if (isShiftLeft)
10400       pic16_genLeftShiftLiteral (left,right,result,ic);
10401     else
10402       genRightShiftLiteral (left,right,result,ic, sign);
10403
10404     goto release;
10405   } // if (right is literal)
10406
10407   /* shift count is unknown then we have to form a loop.
10408    * Note: we take only the lower order byte since shifting
10409    * more than 32 bits make no sense anyway, ( the
10410    * largest size of an object can be only 32 bits )
10411    * Note: we perform arithmetic shifts if the left operand is
10412    * signed and we do an (effective) right shift, i. e. we
10413    * shift in the sign bit from the left. */
10414    
10415   label_complete = newiTempLabel ( NULL );
10416   label_loop_pos = newiTempLabel ( NULL );
10417   label_loop_neg = NULL;
10418   label_negative = NULL;
10419   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10420   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10421
10422   if (signedCount) {
10423     // additional labels needed
10424     label_loop_neg = newiTempLabel ( NULL );
10425     label_negative = newiTempLabel ( NULL );
10426   } // if
10427
10428   // copy source to result -- this will effectively truncate the left operand to the size of result!
10429   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10430   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10431   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10432     pic16_mov2f (AOP(result),AOP(left), offset);
10433   } // for
10434
10435   // if result is longer than left, fill with zeros (or sign)
10436   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10437     if (sign && AOP_SIZE(left) > 0) {
10438       // shift signed operand -- fill with sign
10439       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10440       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10441       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10442       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10444       } // for
10445     } else {
10446       // shift unsigned operand -- fill result with zeros
10447       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10449       } // for
10450     }
10451   } // if (size mismatch)
10452
10453   pic16_mov2w (AOP(right), 0);
10454   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10455   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10456   
10457 #if 0
10458   // perform a shift by one (shift count is positive)
10459   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460   // 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])
10461   pic16_emitpLabel (label_loop_pos->key);
10462   emitCLRC;
10463   if (sign && (pos_shift == POC_RRCF)) {
10464     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10465     emitSETC;
10466   } // if
10467   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10468   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10469   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10470 #else
10471   // perform a shift by one (shift count is positive)
10472   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10473   // 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])
10474   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10475   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10476   emitCLRC;
10477   pic16_emitpLabel (label_loop_pos->key);
10478   if (sign && (pos_shift == POC_RRCF)) {
10479     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10480     emitSETC;
10481   } // if
10482   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10483   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10484   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10485   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10486 #endif
10487
10488   if (signedCount) {
10489     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10490
10491     pic16_emitpLabel (label_negative->key);
10492     // perform a shift by -1 (shift count is negative)
10493     // 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)
10494     emitCLRC;
10495     pic16_emitpLabel (label_loop_neg->key);
10496     if (sign && (neg_shift == POC_RRCF)) {
10497       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10498       emitSETC;
10499     } // if
10500     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10501     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10502     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10503     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10504   } // if (signedCount)
10505
10506   pic16_emitpLabel (label_complete->key);
10507
10508 release:
10509   pic16_freeAsmop (right,NULL,ic,TRUE);
10510   pic16_freeAsmop(left,NULL,ic,TRUE);
10511   pic16_freeAsmop(result,NULL,ic,TRUE);
10512 }
10513
10514 static void genLeftShift (iCode *ic) {
10515   genGenericShift (ic, 1);
10516 }
10517
10518 static void genRightShift (iCode *ic) {
10519   genGenericShift (ic, 0);
10520 }
10521 #endif
10522
10523
10524 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10525 void pic16_loadFSR0(operand *op, int lit)
10526 {
10527   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10528     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10529   } else {
10530     assert (!OP_SYMBOL(op)->remat);
10531     // set up FSR0 with address of result
10532     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10533     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10534   }
10535 }
10536
10537 /*-----------------------------------------------------------------*/
10538 /* genUnpackBits - generates code for unpacking bits               */
10539 /*-----------------------------------------------------------------*/
10540 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10541 {    
10542   int shCnt ;
10543   int rlen = 0 ;
10544   sym_link *etype, *letype;
10545   int blen=0, bstr=0;
10546   int lbstr;
10547   int offset = 0 ;
10548
10549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10550     etype = getSpec(operandType(result));
10551     letype = getSpec(operandType(left));
10552     
10553 //    if(IS_BITFIELD(etype)) {
10554       blen = SPEC_BLEN(etype);
10555       bstr = SPEC_BSTR(etype);
10556 //    }
10557
10558     lbstr = SPEC_BSTR( letype );
10559
10560 #if 1
10561     if((blen == 1) && (bstr < 8)) {
10562       /* it is a single bit, so use the appropriate bit instructions */
10563       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10564
10565       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10566       
10567       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10568       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10569         /* workaround to reduce the extra lfsr instruction */
10570         pic16_emitpcode(POC_BTFSC,
10571               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10572       } else {
10573         pic16_loadFSR0 (left, 0);
10574         pic16_emitpcode(POC_BTFSC,
10575               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10576       }
10577         
10578       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10579
10580       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10581       return;
10582     }
10583
10584 #endif
10585
10586         /* the following call to pic16_loadFSR0 is temporary until
10587          * optimization to handle single bit assignments is added
10588          * to the function. Until then use the old safe way! -- VR */
10589
10590     if (OP_SYMBOL(left)->remat) {
10591         // access symbol directly
10592         pic16_mov2w (AOP(left), 0);
10593     } else {
10594         pic16_loadFSR0( left, 0 );
10595  
10596         /* read the first byte  */
10597         switch (ptype) {
10598                 case POINTER:
10599                 case IPOINTER:
10600                 case PPOINTER:
10601                 case FPOINTER:
10602                 case GPOINTER:
10603                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10604                         break;
10605                 case CPOINTER:
10606                         pic16_emitcode("clr","a");
10607                         pic16_emitcode("movc","a","@a+dptr");
10608                         assert (0);
10609                         break;
10610         }
10611     }
10612
10613         /* if we have bitdisplacement then it fits   */
10614         /* into this byte completely or if length is */
10615         /* less than a byte                          */
10616         if ((shCnt = SPEC_BSTR(etype)) || 
10617                 (SPEC_BLEN(etype) <= 8))  {
10618
10619                 /* shift right acc */
10620                 AccRsh(shCnt, 0);
10621
10622                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10623                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10624
10625 /* VR -- normally I would use the following, but since we use the hack,
10626  * to avoid the masking from AccRsh, why not mask it right now? */
10627
10628 /*
10629                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10630 */
10631
10632                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10633           return ;
10634         }
10635
10636
10637
10638         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10639         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10640         exit(-1);
10641
10642     /* bit field did not fit in a byte  */
10643     rlen = SPEC_BLEN(etype) - 8;
10644     pic16_aopPut(AOP(result),"a",offset++);
10645
10646     while (1)  {
10647
10648         switch (ptype) {
10649         case POINTER:
10650         case IPOINTER:
10651             pic16_emitcode("inc","%s",rname);
10652             pic16_emitcode("mov","a,@%s",rname);
10653             break;
10654             
10655         case PPOINTER:
10656             pic16_emitcode("inc","%s",rname);
10657             pic16_emitcode("movx","a,@%s",rname);
10658             break;
10659
10660         case FPOINTER:
10661             pic16_emitcode("inc","dptr");
10662             pic16_emitcode("movx","a,@dptr");
10663             break;
10664             
10665         case CPOINTER:
10666             pic16_emitcode("clr","a");
10667             pic16_emitcode("inc","dptr");
10668             pic16_emitcode("movc","a","@a+dptr");
10669             break;
10670             
10671         case GPOINTER:
10672             pic16_emitcode("inc","dptr");
10673             pic16_emitcode("lcall","__gptrget");
10674             break;
10675         }
10676
10677         rlen -= 8;            
10678         /* if we are done */
10679         if ( rlen <= 0 )
10680             break ;
10681         
10682         pic16_aopPut(AOP(result),"a",offset++);
10683                               
10684     }
10685     
10686     if (rlen) {
10687         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10688         pic16_aopPut(AOP(result),"a",offset);          
10689     }
10690     
10691     return ;
10692 }
10693
10694
10695 static void genDataPointerGet(operand *left,
10696                               operand *result,
10697                               iCode *ic)
10698 {
10699   int size, offset = 0, leoffset=0 ;
10700
10701         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10702         pic16_aopOp(result, ic, TRUE);
10703
10704         FENTRY;
10705
10706         size = AOP_SIZE(result);
10707 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10708
10709
10710 #if 0
10711         /* The following tests may save a redudant movff instruction when
10712          * accessing unions */
10713          
10714         /* if they are the same */
10715         if (operandsEqu (left, result)) {
10716                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10717                 goto release;
10718         }
10719 #endif
10720
10721 #if 0
10722         /* if they are the same registers */
10723         if (pic16_sameRegs(AOP(left),AOP(result))) {
10724                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10725                 goto release;
10726         }
10727 #endif
10728
10729 #if 1
10730         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10731                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10732                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10733                 goto release;
10734         }
10735 #endif
10736
10737
10738 #if 0
10739         if ( AOP_TYPE(left) == AOP_PCODE) {
10740                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10741                                 AOP(left)->aopu.pcop->name,
10742                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10743                                 PCOR(AOP(left)->aopu.pcop)->instance:
10744                                 PCOI(AOP(left)->aopu.pcop)->offset);
10745         }
10746 #endif
10747
10748         if(AOP(left)->aopu.pcop->type == PO_DIR)
10749                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10750
10751         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10752
10753         while (size--) {
10754                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10755                 
10756 //              pic16_DumpOp("(result)",result);
10757                 if(is_LitAOp(AOP(result))) {
10758                         pic16_mov2w(AOP(left), offset); // patch 8
10759                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10760                 } else {
10761                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10762                                 pic16_popGet(AOP(left), offset), //patch 8
10763                                 pic16_popGet(AOP(result), offset)));
10764                 }
10765
10766                 offset++;
10767                 leoffset++;
10768         }
10769
10770 release:
10771     pic16_freeAsmop(result,NULL,ic,TRUE);
10772 }
10773
10774
10775
10776 /*-----------------------------------------------------------------*/
10777 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10778 /*-----------------------------------------------------------------*/
10779 static void genNearPointerGet (operand *left, 
10780                                operand *result, 
10781                                iCode *ic)
10782 {
10783 //  asmop *aop = NULL;
10784   //regs *preg = NULL ;
10785   sym_link *rtype, *retype;
10786   sym_link *ltype = operandType(left);    
10787
10788     FENTRY;
10789     
10790     rtype = operandType(result);
10791     retype= getSpec(rtype);
10792     
10793     pic16_aopOp(left,ic,FALSE);
10794
10795 //    pic16_DumpOp("(left)",left);
10796 //    pic16_DumpOp("(result)",result);
10797
10798     /* if left is rematerialisable and
10799      * result is not bit variable type and
10800      * the left is pointer to data space i.e
10801      * lower 128 bytes of space */
10802     
10803     if (AOP_TYPE(left) == AOP_PCODE
10804       && !IS_BITFIELD(retype)
10805       && DCL_TYPE(ltype) == POINTER) {
10806
10807         genDataPointerGet (left,result,ic);
10808         pic16_freeAsmop(left, NULL, ic, TRUE);
10809         return ;
10810     }
10811     
10812     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10813     pic16_aopOp (result,ic,TRUE);
10814     
10815     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10816
10817 #if 1
10818     if(IS_BITFIELD( retype )
10819       && (SPEC_BLEN(operandType(result))==1)
10820     ) {
10821       iCode *nextic;
10822       pCodeOp *jop;
10823       int bitstrt, bytestrt;
10824
10825         /* if this is bitfield of size 1, see if we are checking the value
10826          * of a single bit in an if-statement,
10827          * if yes, then don't generate usual code, but execute the
10828          * genIfx directly -- VR */
10829
10830         nextic = ic->next;
10831
10832         /* CHECK: if next iCode is IFX
10833          * and current result operand is nextic's conditional operand
10834          * and current result operand live ranges ends at nextic's key number
10835          */
10836         if((nextic->op == IFX)
10837           && (result == IC_COND(nextic))
10838           && (OP_LIVETO(result) == nextic->seq)
10839           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10840           ) {
10841             /* everything is ok then */
10842             /* find a way to optimize the genIfx iCode */
10843
10844             bytestrt = SPEC_BSTR(operandType(result))/8;
10845             bitstrt = SPEC_BSTR(operandType(result))%8;
10846             
10847             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10848
10849             genIfxpCOpJump(nextic, jop);
10850             
10851             pic16_freeAsmop(left, NULL, ic, TRUE);
10852             pic16_freeAsmop(result, NULL, ic, TRUE);
10853             return;
10854         }
10855     }
10856 #endif
10857
10858
10859     /* if the value is already in a pointer register
10860      * then don't need anything more */
10861     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
10862       /* otherwise get a free pointer register */
10863       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10864                 
10865       ;
10866     }
10867
10868     /* if bitfield then unpack the bits */
10869     if (IS_BITFIELD(retype)) 
10870       genUnpackBits (result, left, NULL, POINTER);
10871     else {
10872       /* we have can just get the values */
10873       int size = AOP_SIZE(result);
10874       int offset = 0;   
10875         
10876       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10877
10878       pic16_loadFSR0( left, 0 );
10879
10880       while(size--) {
10881         if(size) {
10882           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10883                 pic16_popGet(AOP(result), offset++)));
10884         } else {
10885           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10886                 pic16_popGet(AOP(result), offset++)));
10887         }
10888       }
10889     }
10890
10891 #if 0
10892     /* now some housekeeping stuff */
10893     if (aop) {
10894       /* we had to allocate for this iCode */
10895       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10896       pic16_freeAsmop(NULL,aop,ic,TRUE);
10897     } else { 
10898       /* we did not allocate which means left
10899        * already in a pointer register, then
10900        * if size > 0 && this could be used again
10901        * we have to point it back to where it 
10902        * belongs */
10903       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10904       if (AOP_SIZE(result) > 1
10905         && !OP_SYMBOL(left)->remat
10906         && ( OP_SYMBOL(left)->liveTo > ic->seq
10907             || ic->depth )) {
10908 //        int size = AOP_SIZE(result) - 1;
10909 //        while (size--)
10910 //          pic16_emitcode("dec","%s",rname);
10911         }
10912     }
10913 #endif
10914
10915     /* done */
10916     pic16_freeAsmop(left,NULL,ic,TRUE);
10917     pic16_freeAsmop(result,NULL,ic,TRUE);
10918 }
10919
10920 /*-----------------------------------------------------------------*/
10921 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10922 /*-----------------------------------------------------------------*/
10923 static void genPagedPointerGet (operand *left, 
10924                                operand *result, 
10925                                iCode *ic)
10926 {
10927     asmop *aop = NULL;
10928     regs *preg = NULL ;
10929     char *rname ;
10930     sym_link *rtype, *retype;    
10931
10932     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10933
10934     rtype = operandType(result);
10935     retype= getSpec(rtype);
10936     
10937     pic16_aopOp(left,ic,FALSE);
10938
10939   /* if the value is already in a pointer register
10940        then don't need anything more */
10941     if (!AOP_INPREG(AOP(left))) {
10942         /* otherwise get a free pointer register */
10943         aop = newAsmop(0);
10944         preg = getFreePtr(ic,&aop,FALSE);
10945         pic16_emitcode("mov","%s,%s",
10946                 preg->name,
10947                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10948         rname = preg->name ;
10949     } else
10950         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10951     
10952     pic16_freeAsmop(left,NULL,ic,TRUE);
10953     pic16_aopOp (result,ic,TRUE);
10954
10955     /* if bitfield then unpack the bits */
10956     if (IS_BITFIELD(retype)) 
10957         genUnpackBits (result,left,rname,PPOINTER);
10958     else {
10959         /* we have can just get the values */
10960         int size = AOP_SIZE(result);
10961         int offset = 0 ;        
10962         
10963         while (size--) {
10964             
10965             pic16_emitcode("movx","a,@%s",rname);
10966             pic16_aopPut(AOP(result),"a",offset);
10967             
10968             offset++ ;
10969             
10970             if (size)
10971                 pic16_emitcode("inc","%s",rname);
10972         }
10973     }
10974
10975     /* now some housekeeping stuff */
10976     if (aop) {
10977         /* we had to allocate for this iCode */
10978         pic16_freeAsmop(NULL,aop,ic,TRUE);
10979     } else { 
10980         /* we did not allocate which means left
10981            already in a pointer register, then
10982            if size > 0 && this could be used again
10983            we have to point it back to where it 
10984            belongs */
10985         if (AOP_SIZE(result) > 1 &&
10986             !OP_SYMBOL(left)->remat &&
10987             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10988               ic->depth )) {
10989             int size = AOP_SIZE(result) - 1;
10990             while (size--)
10991                 pic16_emitcode("dec","%s",rname);
10992         }
10993     }
10994
10995     /* done */
10996     pic16_freeAsmop(result,NULL,ic,TRUE);
10997     
10998         
10999 }
11000
11001 /*-----------------------------------------------------------------*/
11002 /* genFarPointerGet - gget value from far space                    */
11003 /*-----------------------------------------------------------------*/
11004 static void genFarPointerGet (operand *left,
11005                               operand *result, iCode *ic)
11006 {
11007     int size, offset ;
11008     sym_link *retype = getSpec(operandType(result));
11009
11010     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11011
11012     pic16_aopOp(left,ic,FALSE);
11013
11014     /* if the operand is already in dptr 
11015     then we do nothing else we move the value to dptr */
11016     if (AOP_TYPE(left) != AOP_STR) {
11017         /* if this is remateriazable */
11018         if (AOP_TYPE(left) == AOP_IMMD)
11019             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11020         else { /* we need to get it byte by byte */
11021             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11022             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11023             if (options.model == MODEL_FLAT24)
11024             {
11025                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11026             }
11027         }
11028     }
11029     /* so dptr know contains the address */
11030     pic16_freeAsmop(left,NULL,ic,TRUE);
11031     pic16_aopOp(result,ic,TRUE);
11032
11033     /* if bit then unpack */
11034     if (IS_BITFIELD(retype)) 
11035         genUnpackBits(result,left,"dptr",FPOINTER);
11036     else {
11037         size = AOP_SIZE(result);
11038         offset = 0 ;
11039
11040         while (size--) {
11041             pic16_emitcode("movx","a,@dptr");
11042             pic16_aopPut(AOP(result),"a",offset++);
11043             if (size)
11044                 pic16_emitcode("inc","dptr");
11045         }
11046     }
11047
11048     pic16_freeAsmop(result,NULL,ic,TRUE);
11049 }
11050
11051 #if 0
11052 /*-----------------------------------------------------------------*/
11053 /* genCodePointerGet - get value from code space                  */
11054 /*-----------------------------------------------------------------*/
11055 static void genCodePointerGet (operand *left,
11056                                 operand *result, iCode *ic)
11057 {
11058     int size, offset ;
11059     sym_link *retype = getSpec(operandType(result));
11060
11061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11062
11063     pic16_aopOp(left,ic,FALSE);
11064
11065     /* if the operand is already in dptr 
11066     then we do nothing else we move the value to dptr */
11067     if (AOP_TYPE(left) != AOP_STR) {
11068         /* if this is remateriazable */
11069         if (AOP_TYPE(left) == AOP_IMMD)
11070             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11071         else { /* we need to get it byte by byte */
11072             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11073             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11074             if (options.model == MODEL_FLAT24)
11075             {
11076                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11077             }
11078         }
11079     }
11080     /* so dptr know contains the address */
11081     pic16_freeAsmop(left,NULL,ic,TRUE);
11082     pic16_aopOp(result,ic,FALSE);
11083
11084     /* if bit then unpack */
11085     if (IS_BITFIELD(retype)) 
11086         genUnpackBits(result,left,"dptr",CPOINTER);
11087     else {
11088         size = AOP_SIZE(result);
11089         offset = 0 ;
11090
11091         while (size--) {
11092             pic16_emitcode("clr","a");
11093             pic16_emitcode("movc","a,@a+dptr");
11094             pic16_aopPut(AOP(result),"a",offset++);
11095             if (size)
11096                 pic16_emitcode("inc","dptr");
11097         }
11098     }
11099
11100     pic16_freeAsmop(result,NULL,ic,TRUE);
11101 }
11102 #endif
11103
11104 #if 0
11105 /*-----------------------------------------------------------------*/
11106 /* genGenPointerGet - gget value from generic pointer space        */
11107 /*-----------------------------------------------------------------*/
11108 static void genGenPointerGet (operand *left,
11109                               operand *result, iCode *ic)
11110 {
11111   int size, offset, lit;
11112   sym_link *retype = getSpec(operandType(result));
11113
11114         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11115         pic16_aopOp(left,ic,FALSE);
11116         pic16_aopOp(result,ic,FALSE);
11117         size = AOP_SIZE(result);
11118
11119         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11120
11121         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11122
11123                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11124                 // load FSR0 from immediate
11125                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11126
11127 //              pic16_loadFSR0( left );
11128
11129                 offset = 0;
11130                 while(size--) {
11131                         if(size) {
11132                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11133                         } else {
11134                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11135                         }
11136                         offset++;
11137                 }
11138                 goto release;
11139
11140         }
11141         else { /* we need to get it byte by byte */
11142                 // set up FSR0 with address from left
11143                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11144                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11145                 
11146                 offset = 0 ;
11147
11148                 while(size--) {
11149                         if(size) {
11150                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11151                         } else {
11152                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11153                         }
11154                         offset++;
11155                 }
11156                 goto release;
11157         }
11158
11159   /* if bit then unpack */
11160         if (IS_BITFIELD(retype)) 
11161                 genUnpackBits(result,left,"BAD",GPOINTER);
11162
11163         release:
11164         pic16_freeAsmop(left,NULL,ic,TRUE);
11165         pic16_freeAsmop(result,NULL,ic,TRUE);
11166
11167 }
11168 #endif
11169
11170
11171 /*-----------------------------------------------------------------*/
11172 /* genGenPointerGet - gget value from generic pointer space        */
11173 /*-----------------------------------------------------------------*/
11174 static void genGenPointerGet (operand *left,
11175                               operand *result, iCode *ic)
11176 {
11177   int size, offset, lit;
11178   sym_link *retype = getSpec(operandType(result));
11179
11180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11181     pic16_aopOp(left,ic,FALSE);
11182     pic16_aopOp(result,ic,TRUE);
11183     size = AOP_SIZE(result);
11184
11185     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11186
11187     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11188
11189       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11190       // load FSR0 from immediate
11191       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11192
11193       werror(W_POSSBUG2, __FILE__, __LINE__);
11194
11195       offset = 0;
11196       while(size--) {
11197         if(size) {
11198           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11199         } else {
11200           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11201         }
11202         offset++;
11203       }
11204
11205       goto release;
11206
11207     } else { /* we need to get it byte by byte */
11208
11209       /* set up WREG:PRODL:FSR0L with address from left */
11210       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11211       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11212       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11213       
11214       pic16_callGenericPointerRW(0, size);
11215       
11216       assignResultValue(result, 1);
11217       
11218       goto release;
11219     }
11220
11221   /* if bit then unpack */
11222     if (IS_BITFIELD(retype)) 
11223       genUnpackBits(result,left,"BAD",GPOINTER);
11224
11225 release:
11226   pic16_freeAsmop(left,NULL,ic,TRUE);
11227   pic16_freeAsmop(result,NULL,ic,TRUE);
11228 }
11229
11230 /*-----------------------------------------------------------------*/
11231 /* genConstPointerGet - get value from const generic pointer space */
11232 /*-----------------------------------------------------------------*/
11233 static void genConstPointerGet (operand *left,
11234                                 operand *result, iCode *ic)
11235 {
11236   //sym_link *retype = getSpec(operandType(result));
11237   // symbol *albl = newiTempLabel(NULL);        // patch 15
11238   // symbol *blbl = newiTempLabel(NULL);        //
11239   // PIC_OPCODE poc;                            // patch 15
11240   int size;
11241   int offset = 0;
11242
11243   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11244   pic16_aopOp(left,ic,FALSE);
11245   pic16_aopOp(result,ic,TRUE);
11246   size = AOP_SIZE(result);
11247
11248   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11249
11250   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11251
11252   // set up table pointer
11253   if( (AOP_TYPE(left) == AOP_PCODE) 
11254       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11255           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11256     {
11257       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11258       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11259       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11260       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11261       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11262       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11263   } else {
11264     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11265     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11266     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11267   }
11268
11269   while(size--) {
11270     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11271     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11272     offset++;
11273   }
11274     
11275   pic16_freeAsmop(left,NULL,ic,TRUE);
11276   pic16_freeAsmop(result,NULL,ic,TRUE);
11277 }
11278
11279
11280 /*-----------------------------------------------------------------*/
11281 /* genPointerGet - generate code for pointer get                   */
11282 /*-----------------------------------------------------------------*/
11283 static void genPointerGet (iCode *ic)
11284 {
11285   operand *left, *result ;
11286   sym_link *type, *etype;
11287   int p_type;
11288
11289     FENTRY;
11290     
11291     left = IC_LEFT(ic);
11292     result = IC_RESULT(ic) ;
11293
11294     /* depending on the type of pointer we need to
11295     move it to the correct pointer register */
11296     type = operandType(left);
11297     etype = getSpec(type);
11298
11299 #if 0
11300     if (IS_PTR_CONST(type))
11301 #else
11302     if (IS_CODEPTR(type))
11303 #endif
11304       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11305
11306     /* if left is of type of pointer then it is simple */
11307     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11308       p_type = DCL_TYPE(type);
11309     else {
11310       /* we have to go by the storage class */
11311       p_type = PTR_TYPE(SPEC_OCLS(etype));
11312
11313       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11314
11315       if (SPEC_OCLS(etype)->codesp ) {
11316         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11317         //p_type = CPOINTER ;   
11318       } else
11319       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11320         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11321         /*p_type = FPOINTER ;*/ 
11322       } else
11323       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11324         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11325         /* p_type = PPOINTER; */
11326       } else
11327       if (SPEC_OCLS(etype) == idata ) {
11328         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11329         /* p_type = IPOINTER; */
11330       } else {
11331         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11332         /* p_type = POINTER ; */
11333       }
11334     }
11335
11336     /* now that we have the pointer type we assign
11337     the pointer values */
11338     switch (p_type) {
11339       case POINTER:     
11340       case IPOINTER:
11341         genNearPointerGet (left,result,ic);
11342         break;
11343
11344       case PPOINTER:
11345         genPagedPointerGet(left,result,ic);
11346         break;
11347
11348       case FPOINTER:
11349         genFarPointerGet (left,result,ic);
11350         break;
11351
11352       case CPOINTER:
11353         genConstPointerGet (left,result,ic);
11354         //pic16_emitcodePointerGet (left,result,ic);
11355         break;
11356
11357       case GPOINTER:
11358 #if 0
11359       if (IS_PTR_CONST(type))
11360         genConstPointerGet (left,result,ic);
11361       else
11362 #endif
11363         genGenPointerGet (left,result,ic);
11364       break;
11365
11366     default:
11367       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11368               "genPointerGet: illegal pointer type");
11369     
11370     }
11371 }
11372
11373 /*-----------------------------------------------------------------*/
11374 /* genPackBits - generates code for packed bit storage             */
11375 /*-----------------------------------------------------------------*/
11376 static void genPackBits (sym_link    *etype , operand *result,
11377                          operand *right ,
11378                          char *rname, int p_type)
11379 {
11380   int shCnt = 0 ;
11381   int offset = 0  ;
11382   int rLen = 0 ;
11383   int blen, bstr ;   
11384   sym_link *retype;
11385
11386         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11387         blen = SPEC_BLEN(etype);
11388         bstr = SPEC_BSTR(etype);
11389
11390         retype = getSpec(operandType(right));
11391
11392         if(AOP_TYPE(right) == AOP_LIT) {
11393                 if((blen == 1) && (bstr < 8)) {
11394                   unsigned long lit;
11395                         /* it is a single bit, so use the appropriate bit instructions */
11396
11397                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11398
11399                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11400 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11401                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11402                                 /* workaround to reduce the extra lfsr instruction */
11403                                 if(lit) {
11404                                         pic16_emitpcode(POC_BSF,
11405                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11406                                 } else {
11407                                         pic16_emitpcode(POC_BCF,
11408                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11409                                 }
11410                         } else {
11411                                 pic16_loadFSR0(result, 0);
11412                                 if(lit) {
11413                                         pic16_emitpcode(POC_BSF,
11414                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11415                                 } else {
11416                                         pic16_emitpcode(POC_BCF,
11417                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11418                                 }
11419                         }
11420         
11421                   return;
11422                 }
11423                 /* move literal to W */
11424                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11425                 offset++;
11426         } else
11427         if(IS_BITFIELD(retype) 
11428           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11429           && (blen == 1)) {
11430           int rblen, rbstr;
11431
11432             rblen = SPEC_BLEN( retype );
11433             rbstr = SPEC_BSTR( retype );
11434             
11435
11436             if(IS_BITFIELD(etype)) {
11437               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11438               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11439             } else {
11440               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11441             }
11442             
11443             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11444             
11445             if(IS_BITFIELD(etype)) {
11446               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11447             } else {
11448               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11449             }
11450
11451             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11452             
11453             return;
11454         } else {
11455           /* move right to W */
11456           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11457         }
11458
11459         /* if the bit length is less than or   */
11460         /* it exactly fits a byte then         */
11461         if((shCnt=SPEC_BSTR(etype))
11462                 || SPEC_BLEN(etype) <= 8 )  {
11463                 int fsr0_setup = 0;
11464
11465                 if (blen != 8 || bstr != 0) {
11466                   // we need to combine the value with the old value
11467                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11468
11469           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11470                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11471                 
11472                   /* shift left acc */
11473                   AccLsh(shCnt);
11474
11475                   /* using PRODH as a temporary register here */
11476                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11477
11478                  if (OP_SYMBOL(result)->remat) {
11479                    // access symbol directly
11480                    pic16_mov2w (AOP(result), 0);
11481                  } else {
11482                   /* get old value */
11483                   switch (p_type) {
11484                         case FPOINTER:
11485                         case POINTER:
11486                                 pic16_loadFSR0( result, 0 );
11487                                 fsr0_setup = 1;
11488                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11489 //                              pic16_emitcode ("mov","b,a");
11490 //                              pic16_emitcode("mov","a,@%s",rname);
11491                                 break;
11492
11493                         case GPOINTER:
11494                                 if (AOP(result)->aopu.aop_reg[2]) {
11495                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11496                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11497                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11498                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11499
11500                                   pic16_callGenericPointerRW(0, 1);
11501                                 } else {
11502                                   // data pointer (just 2 byte given)
11503                                   pic16_loadFSR0( result, 0 );
11504                                   fsr0_setup = 1;
11505                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11506                                 }
11507                                 
11508                                 // warnings will be emitted below (if desired)
11509                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11510                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11511                                 break;
11512
11513                         default:
11514                                 assert (0 && "invalid pointer type specified");
11515                                 break;
11516                   }
11517                  }
11518 #if 1
11519                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11520                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11521                                         (unsigned char)(0xff >> (8-bstr))) ));
11522                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11523                 } // if (blen != 8 || bstr != 0)
11524
11525                 /* write new value back */
11526                if (OP_SYMBOL(result)->remat) {
11527                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11528                } else {
11529                 switch (p_type) {
11530                         case FPOINTER:
11531                         case POINTER:
11532                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11533                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11534                                 break;
11535
11536                         case GPOINTER:
11537                                 if (AOP(result)->aopu.aop_reg[2]) {
11538                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11539                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11540                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11541                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11542                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11543                                   
11544                                   pic16_callGenericPointerRW(1, 1);
11545                                 } else {
11546                                   // data pointer (just 2 byte given)
11547                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11548                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11549                                 }
11550                                 
11551                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11552                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11553                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11554                                 break;
11555
11556                         default:
11557                                 assert (0 && "invalid pointer type specified");
11558                                 break;
11559                 }
11560                }
11561 #endif
11562
11563           return;
11564         }
11565
11566
11567 #if 0
11568         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11569         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11570         exit(-1);
11571 #endif
11572
11573
11574     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11575     rLen = SPEC_BLEN(etype)-8;
11576     
11577     /* now generate for lengths greater than one byte */
11578     while (1) {
11579         rLen -= 8 ;
11580         if (rLen <= 0 ) {
11581           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11582           break ;
11583         }
11584
11585         switch (p_type) {
11586             case POINTER:
11587                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11588                 break;
11589
11590 /*
11591             case FPOINTER:
11592                 MOVA(l);
11593                 pic16_emitcode("movx","@dptr,a");
11594                 break;
11595
11596             case GPOINTER:
11597                 MOVA(l);
11598                 DEBUGpic16_emitcode(";lcall","__gptrput");
11599                 break;  
11600 */
11601           default:
11602             assert(0);
11603         }   
11604
11605
11606         pic16_mov2w(AOP(right), offset++);
11607     }
11608
11609     /* last last was not complete */
11610     if (rLen)   {
11611         /* save the byte & read byte */
11612         switch (p_type) {
11613             case POINTER:
11614 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11615                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11616                 break;
11617
11618 /*
11619             case FPOINTER:
11620                 pic16_emitcode ("mov","b,a");
11621                 pic16_emitcode("movx","a,@dptr");
11622                 break;
11623
11624             case GPOINTER:
11625                 pic16_emitcode ("push","b");
11626                 pic16_emitcode ("push","acc");
11627                 pic16_emitcode ("lcall","__gptrget");
11628                 pic16_emitcode ("pop","b");
11629                 break;
11630 */
11631             default:
11632               assert(0);
11633         }
11634         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11635         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11636         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11637 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11638 //        pic16_emitcode ("orl","a,b");
11639     }
11640
11641 //    if (p_type == GPOINTER)
11642 //        pic16_emitcode("pop","b");
11643
11644     switch (p_type) {
11645
11646       case POINTER:
11647         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11648 //      pic16_emitcode("mov","@%s,a",rname);
11649         break;
11650 /*
11651       case FPOINTER:
11652         pic16_emitcode("movx","@dptr,a");
11653         break;
11654         
11655       case GPOINTER:
11656         DEBUGpic16_emitcode(";lcall","__gptrput");
11657         break;                  
11658 */
11659       default:
11660         assert(0);
11661     }
11662     
11663 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11664 }
11665 /*-----------------------------------------------------------------*/
11666 /* genDataPointerSet - remat pointer to data space                 */
11667 /*-----------------------------------------------------------------*/
11668 static void genDataPointerSet(operand *right,
11669                               operand *result,
11670                               iCode *ic)
11671 {
11672     int size, offset = 0, resoffset=0 ;
11673
11674     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11675     pic16_aopOp(right,ic,FALSE);
11676
11677     size = AOP_SIZE(right);
11678
11679 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11680
11681 #if 0
11682     if ( AOP_TYPE(result) == AOP_PCODE) {
11683       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11684               AOP(result)->aopu.pcop->name,
11685                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11686               PCOR(AOP(result)->aopu.pcop)->instance:
11687               PCOI(AOP(result)->aopu.pcop)->offset);
11688     }
11689 #endif
11690
11691         if(AOP(result)->aopu.pcop->type == PO_DIR)
11692                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11693
11694         while (size--) {
11695                 if (AOP_TYPE(right) == AOP_LIT) {
11696                   unsigned int lit;
11697
11698                     if(!IS_FLOAT(operandType( right )))
11699                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11700                     else {
11701                       union {
11702                         unsigned long lit_int;
11703                         float lit_float;
11704                       } info;
11705         
11706                         /* take care if literal is a float */
11707                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11708                         lit = info.lit_int;
11709                     }
11710
11711                     lit = lit >> (8*offset);
11712                     if(lit&0xff) {
11713                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11714                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11715                     } else {
11716                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11717                     }
11718                 } else {
11719                   pic16_mov2w(AOP(right), offset);
11720                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11721                 }
11722                 offset++;
11723                 resoffset++;
11724         }
11725
11726     pic16_freeAsmop(right,NULL,ic,TRUE);
11727 }
11728
11729
11730
11731 /*-----------------------------------------------------------------*/
11732 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11733 /*-----------------------------------------------------------------*/
11734 static void genNearPointerSet (operand *right,
11735                                operand *result, 
11736                                iCode *ic)
11737 {
11738   asmop *aop = NULL;
11739   sym_link *retype;
11740   sym_link *ptype = operandType(result);
11741   sym_link *resetype;
11742     
11743         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11744         retype= getSpec(operandType(right));
11745         resetype = getSpec(operandType(result));
11746   
11747         pic16_aopOp(result,ic,FALSE);
11748     
11749         /* if the result is rematerializable &
11750          * in data space & not a bit variable */
11751         
11752         /* and result is not a bit variable */
11753         if (AOP_TYPE(result) == AOP_PCODE
11754 //              && AOP_TYPE(result) == AOP_IMMD
11755                 && DCL_TYPE(ptype) == POINTER
11756                 && !IS_BITFIELD(retype)
11757                 && !IS_BITFIELD(resetype)) {
11758
11759                 genDataPointerSet (right,result,ic);
11760                 pic16_freeAsmop(result,NULL,ic,TRUE);
11761           return;
11762         }
11763
11764         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11765         pic16_aopOp(right,ic,FALSE);
11766         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11767
11768         /* if the value is already in a pointer register
11769          * then don't need anything more */
11770         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11771           /* otherwise get a free pointer register */
11772           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11773
11774           ;
11775         }
11776
11777         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11778
11779         /* if bitfield then unpack the bits */
11780         if (IS_BITFIELD(resetype)) {
11781                 genPackBits (resetype, result, right, NULL, POINTER);
11782         } else {
11783                 /* we have can just get the values */
11784           int size = AOP_SIZE(right);
11785           int offset = 0 ;    
11786
11787             pic16_loadFSR0(result, 0);
11788             
11789                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11790                 while (size--) {
11791                                 if (AOP_TYPE(right) == AOP_LIT) {
11792                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11793                                         if (size) {
11794                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11795                                         } else {
11796                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11797                                         }
11798                                 } else { // no literal
11799                                         if(size) {
11800                                                 pic16_emitpcode(POC_MOVFF,
11801                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11802                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11803                                         } else {
11804                                                 pic16_emitpcode(POC_MOVFF,
11805                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11806                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11807                                         }
11808                                 }
11809                         offset++;
11810                 }
11811         }
11812
11813         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11814         /* now some housekeeping stuff */
11815         if (aop) {
11816           /* we had to allocate for this iCode */
11817           pic16_freeAsmop(NULL,aop,ic,TRUE);
11818         } else { 
11819           /* we did not allocate which means left
11820            * already in a pointer register, then
11821            * if size > 0 && this could be used again
11822            * we have to point it back to where it 
11823            * belongs */
11824           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11825           if (AOP_SIZE(right) > 1
11826             && !OP_SYMBOL(result)->remat
11827             && ( OP_SYMBOL(result)->liveTo > ic->seq
11828             || ic->depth )) {
11829
11830               int size = AOP_SIZE(right) - 1;
11831
11832                 while (size--)
11833                   pic16_emitcode("decf","fsr0,f");
11834                   //pic16_emitcode("dec","%s",rname);
11835             }
11836         }
11837
11838     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11839     /* done */
11840 //release:
11841     pic16_freeAsmop(right,NULL,ic,TRUE);
11842     pic16_freeAsmop(result,NULL,ic,TRUE);
11843 }
11844
11845 /*-----------------------------------------------------------------*/
11846 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11847 /*-----------------------------------------------------------------*/
11848 static void genPagedPointerSet (operand *right,
11849                                operand *result, 
11850                                iCode *ic)
11851 {
11852     asmop *aop = NULL;
11853     regs *preg = NULL ;
11854     char *rname , *l;
11855     sym_link *retype;
11856        
11857     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11858
11859     retype= getSpec(operandType(right));
11860     
11861     pic16_aopOp(result,ic,FALSE);
11862     
11863     /* if the value is already in a pointer register
11864        then don't need anything more */
11865     if (!AOP_INPREG(AOP(result))) {
11866         /* otherwise get a free pointer register */
11867         aop = newAsmop(0);
11868         preg = getFreePtr(ic,&aop,FALSE);
11869         pic16_emitcode("mov","%s,%s",
11870                 preg->name,
11871                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11872         rname = preg->name ;
11873     } else
11874         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11875     
11876     pic16_freeAsmop(result,NULL,ic,TRUE);
11877     pic16_aopOp (right,ic,FALSE);
11878
11879     /* if bitfield then unpack the bits */
11880     if (IS_BITFIELD(retype)) 
11881         genPackBits (retype,result,right,rname,PPOINTER);
11882     else {
11883         /* we have can just get the values */
11884         int size = AOP_SIZE(right);
11885         int offset = 0 ;        
11886         
11887         while (size--) {
11888             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11889             
11890             MOVA(l);
11891             pic16_emitcode("movx","@%s,a",rname);
11892
11893             if (size)
11894                 pic16_emitcode("inc","%s",rname);
11895
11896             offset++;
11897         }
11898     }
11899     
11900     /* now some housekeeping stuff */
11901     if (aop) {
11902         /* we had to allocate for this iCode */
11903         pic16_freeAsmop(NULL,aop,ic,TRUE);
11904     } else { 
11905         /* we did not allocate which means left
11906            already in a pointer register, then
11907            if size > 0 && this could be used again
11908            we have to point it back to where it 
11909            belongs */
11910         if (AOP_SIZE(right) > 1 &&
11911             !OP_SYMBOL(result)->remat &&
11912             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11913               ic->depth )) {
11914             int size = AOP_SIZE(right) - 1;
11915             while (size--)
11916                 pic16_emitcode("dec","%s",rname);
11917         }
11918     }
11919
11920     /* done */
11921     pic16_freeAsmop(right,NULL,ic,TRUE);
11922     
11923         
11924 }
11925
11926 /*-----------------------------------------------------------------*/
11927 /* genFarPointerSet - set value from far space                     */
11928 /*-----------------------------------------------------------------*/
11929 static void genFarPointerSet (operand *right,
11930                               operand *result, iCode *ic)
11931 {
11932     int size, offset ;
11933     sym_link *retype = getSpec(operandType(right));
11934
11935     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11936     pic16_aopOp(result,ic,FALSE);
11937
11938     /* if the operand is already in dptr 
11939     then we do nothing else we move the value to dptr */
11940     if (AOP_TYPE(result) != AOP_STR) {
11941         /* if this is remateriazable */
11942         if (AOP_TYPE(result) == AOP_IMMD)
11943             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11944         else { /* we need to get it byte by byte */
11945             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11946             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11947             if (options.model == MODEL_FLAT24)
11948             {
11949                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11950             }
11951         }
11952     }
11953     /* so dptr know contains the address */
11954     pic16_freeAsmop(result,NULL,ic,TRUE);
11955     pic16_aopOp(right,ic,FALSE);
11956
11957     /* if bit then unpack */
11958     if (IS_BITFIELD(retype)) 
11959         genPackBits(retype,result,right,"dptr",FPOINTER);
11960     else {
11961         size = AOP_SIZE(right);
11962         offset = 0 ;
11963
11964         while (size--) {
11965             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11966             MOVA(l);
11967             pic16_emitcode("movx","@dptr,a");
11968             if (size)
11969                 pic16_emitcode("inc","dptr");
11970         }
11971     }
11972
11973     pic16_freeAsmop(right,NULL,ic,TRUE);
11974 }
11975
11976 /*-----------------------------------------------------------------*/
11977 /* genGenPointerSet - set value from generic pointer space         */
11978 /*-----------------------------------------------------------------*/
11979 #if 0
11980 static void genGenPointerSet (operand *right,
11981                               operand *result, iCode *ic)
11982 {
11983         int i, size, offset, lit;
11984         sym_link *retype = getSpec(operandType(right));
11985
11986         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11987
11988         pic16_aopOp(result,ic,FALSE);
11989         pic16_aopOp(right,ic,FALSE);
11990         size = AOP_SIZE(right);
11991         offset = 0;
11992
11993         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11994
11995         /* if the operand is already in dptr 
11996                 then we do nothing else we move the value to dptr */
11997         if (AOP_TYPE(result) != AOP_STR) {
11998                 /* if this is remateriazable */
11999                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12000                 // WARNING: anythig until "else" is untested!
12001                 if (AOP_TYPE(result) == AOP_IMMD) {
12002                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12003                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12004                         // load FSR0 from immediate
12005                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12006                         offset = 0;
12007                         while(size--) {
12008                                 if(size) {
12009                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12010                                 } else {
12011                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12012                                 }
12013                                 offset++;
12014                         }
12015                         goto release;
12016                 }
12017                 else { /* we need to get it byte by byte */
12018                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12019                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12020
12021                         // set up FSR0 with address of result
12022                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12023                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12024
12025                         /* hack hack! see if this the FSR. If so don't load W */
12026                         if(AOP_TYPE(right) != AOP_ACC) {
12027
12028                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12029
12030                                 if(AOP_TYPE(right) == AOP_LIT)
12031                                 {
12032                                         // copy literal
12033                                         // note: pic16_popGet handles sign extension
12034                                         for(i=0;i<size;i++) {
12035                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12036                                                 if(i < size-1)
12037                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12038                                                 else
12039                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12040                                         }
12041                                 } else {
12042                                         // copy regs
12043
12044                                         for(i=0;i<size;i++) {
12045                                                 if(i < size-1)
12046                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12047                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12048                                                 else
12049                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12050                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12051                                         }
12052                                 }
12053                                 goto release;
12054                         } 
12055                         // right = ACC
12056                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12057                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12058                         goto release;
12059         } // if (AOP_TYPE(result) != AOP_IMMD)
12060
12061         } // if (AOP_TYPE(result) != AOP_STR)
12062         /* so dptr know contains the address */
12063
12064
12065         /* if bit then unpack */
12066         if (IS_BITFIELD(retype)) 
12067                 genPackBits(retype,result,right,"dptr",GPOINTER);
12068         else {
12069                 size = AOP_SIZE(right);
12070                 offset = 0 ;
12071
12072                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12073
12074                 // set up FSR0 with address of result
12075                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12076                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12077         
12078                 while (size--) {
12079                         if (AOP_TYPE(right) == AOP_LIT) {
12080                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12081                                 if (size) {
12082                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12083                                 } else {
12084                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12085                                 }
12086                         } else { // no literal
12087                                 if(size) {
12088                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12089                                 } else {
12090                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12091                                 }
12092                         }
12093                         offset++;
12094                 }
12095         }
12096
12097         release:
12098         pic16_freeAsmop(right,NULL,ic,TRUE);
12099         pic16_freeAsmop(result,NULL,ic,TRUE);
12100 }
12101 #endif
12102
12103 static void genGenPointerSet (operand *right,
12104                               operand *result, iCode *ic)
12105 {
12106   int size;
12107   sym_link *retype = getSpec(operandType(result));
12108
12109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12110
12111     pic16_aopOp(result,ic,FALSE);
12112     pic16_aopOp(right,ic,FALSE);
12113     size = AOP_SIZE(right);
12114
12115     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12116
12117
12118     /* if bit then unpack */
12119     if (IS_BITFIELD(retype)) {
12120 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12121       genPackBits(retype,result,right,"dptr",GPOINTER);
12122       goto release;
12123     }
12124
12125     size = AOP_SIZE(right);
12126
12127     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12128
12129
12130
12131     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12132
12133     /* value of right+0 is placed on stack, which will be retrieved
12134      * by the support function this restoring the stack. The important
12135      * thing is that there is no need to manually restore stack pointer
12136      * here */
12137     pushaop(AOP(right), 0);
12138 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12139     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12140     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12141     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12142     
12143     /* load address to write to in WREG:FSR0H:FSR0L */
12144     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12145                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12146     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12147                                 pic16_popCopyReg(&pic16_pc_prodl)));
12148     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12149     
12150     pic16_callGenericPointerRW(1, size);
12151
12152 release:
12153     pic16_freeAsmop(right,NULL,ic,TRUE);
12154     pic16_freeAsmop(result,NULL,ic,TRUE);
12155 }
12156
12157 /*-----------------------------------------------------------------*/
12158 /* genPointerSet - stores the value into a pointer location        */
12159 /*-----------------------------------------------------------------*/
12160 static void genPointerSet (iCode *ic)
12161 {    
12162   operand *right, *result ;
12163   sym_link *type, *etype;
12164   int p_type;
12165
12166     FENTRY;
12167
12168     right = IC_RIGHT(ic);
12169     result = IC_RESULT(ic) ;
12170
12171     /* depending on the type of pointer we need to
12172     move it to the correct pointer register */
12173     type = operandType(result);
12174     etype = getSpec(type);
12175     
12176     /* if left is of type of pointer then it is simple */
12177     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12178         p_type = DCL_TYPE(type);
12179     }
12180     else {
12181         /* we have to go by the storage class */
12182         p_type = PTR_TYPE(SPEC_OCLS(etype));
12183
12184 /*      if (SPEC_OCLS(etype)->codesp ) { */
12185 /*          p_type = CPOINTER ;  */
12186 /*      } */
12187 /*      else */
12188 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12189 /*              p_type = FPOINTER ; */
12190 /*          else */
12191 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12192 /*                  p_type = PPOINTER ; */
12193 /*              else */
12194 /*                  if (SPEC_OCLS(etype) == idata ) */
12195 /*                      p_type = IPOINTER ; */
12196 /*                  else */
12197 /*                      p_type = POINTER ; */
12198     }
12199
12200     /* now that we have the pointer type we assign
12201     the pointer values */
12202     switch (p_type) {
12203       case POINTER:
12204       case IPOINTER:
12205         genNearPointerSet (right,result,ic);
12206         break;
12207
12208       case PPOINTER:
12209         genPagedPointerSet (right,result,ic);
12210         break;
12211
12212       case FPOINTER:
12213         genFarPointerSet (right,result,ic);
12214         break;
12215         
12216       case GPOINTER:
12217         genGenPointerSet (right,result,ic);
12218         break;
12219
12220       default:
12221         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12222           "genPointerSet: illegal pointer type");
12223     }
12224 }
12225
12226 /*-----------------------------------------------------------------*/
12227 /* genIfx - generate code for Ifx statement                        */
12228 /*-----------------------------------------------------------------*/
12229 static void genIfx (iCode *ic, iCode *popIc)
12230 {
12231   operand *cond = IC_COND(ic);
12232   int isbit =0;
12233
12234     FENTRY;
12235
12236     pic16_aopOp(cond,ic,FALSE);
12237
12238     /* get the value into acc */
12239     if (AOP_TYPE(cond) != AOP_CRY)
12240       pic16_toBoolean(cond);
12241     else
12242       isbit = 1;
12243     /* the result is now in the accumulator */
12244     pic16_freeAsmop(cond,NULL,ic,TRUE);
12245
12246     /* if there was something to be popped then do it */
12247     if (popIc)
12248       genIpop(popIc);
12249
12250     /* if the condition is  a bit variable */
12251     if (isbit && IS_ITEMP(cond) && 
12252         SPIL_LOC(cond)) {
12253       genIfxJump(ic,"c");
12254       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12255     } else {
12256       if (isbit && !IS_ITEMP(cond))
12257         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12258         else
12259         genIfxJump(ic,"a");
12260     }
12261     ic->generated = 1;
12262 }
12263
12264 /*-----------------------------------------------------------------*/
12265 /* genAddrOf - generates code for address of                       */
12266 /*-----------------------------------------------------------------*/
12267 static void genAddrOf (iCode *ic)
12268 {
12269   operand *result, *left;
12270   int size;
12271   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12272   pCodeOp *pcop0, *pcop1, *pcop2;
12273
12274     FENTRY;
12275
12276     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12277
12278     sym = OP_SYMBOL( IC_LEFT(ic) );
12279     
12280     if(sym->onStack) {
12281       /* get address of symbol on stack */
12282       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12283 #if 0
12284       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12285                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12286 #endif
12287
12288       // operands on stack are accessible via "FSR2 + index" with index
12289       // starting at 2 for arguments and growing from 0 downwards for
12290       // local variables (index == 0 is not assigned so we add one here)
12291       {
12292         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12293         if (soffs <= 0) {
12294           assert (soffs < 0);
12295           soffs++;
12296         } // if
12297         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12298         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12299         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12300         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12301         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12302         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12303         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12304       }
12305
12306       goto release;
12307     }
12308         
12309 //      if(pic16_debug_verbose) {
12310 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12311 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12312 //      }
12313         
12314     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12315     size = AOP_SIZE(IC_RESULT(ic));
12316
12317     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12318     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12319     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12320         
12321     if (size == 3) {
12322       pic16_emitpcode(POC_MOVLW, pcop0);
12323       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12324       pic16_emitpcode(POC_MOVLW, pcop1);
12325       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12326       pic16_emitpcode(POC_MOVLW, pcop2);
12327       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12328     } else
12329     if (size == 2) {
12330       pic16_emitpcode(POC_MOVLW, pcop0);
12331       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12332       pic16_emitpcode(POC_MOVLW, pcop1);
12333     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12334     } else {
12335       pic16_emitpcode(POC_MOVLW, pcop0);
12336       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12337     }
12338
12339     pic16_freeAsmop(left, NULL, ic, FALSE);
12340 release:
12341     pic16_freeAsmop(result,NULL,ic,TRUE);
12342 }
12343
12344
12345 #if 0
12346 /*-----------------------------------------------------------------*/
12347 /* genFarFarAssign - assignment when both are in far space         */
12348 /*-----------------------------------------------------------------*/
12349 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12350 {
12351     int size = AOP_SIZE(right);
12352     int offset = 0;
12353     char *l ;
12354     /* first push the right side on to the stack */
12355     while (size--) {
12356         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12357         MOVA(l);
12358         pic16_emitcode ("push","acc");
12359     }
12360     
12361     pic16_freeAsmop(right,NULL,ic,FALSE);
12362     /* now assign DPTR to result */
12363     pic16_aopOp(result,ic,FALSE);
12364     size = AOP_SIZE(result);
12365     while (size--) {
12366         pic16_emitcode ("pop","acc");
12367         pic16_aopPut(AOP(result),"a",--offset);
12368     }
12369     pic16_freeAsmop(result,NULL,ic,FALSE);
12370         
12371 }
12372 #endif
12373
12374 /*-----------------------------------------------------------------*/
12375 /* genAssign - generate code for assignment                        */
12376 /*-----------------------------------------------------------------*/
12377 static void genAssign (iCode *ic)
12378 {
12379   operand *result, *right;
12380   int size, offset,know_W;
12381   unsigned long lit = 0L;
12382
12383   result = IC_RESULT(ic);
12384   right  = IC_RIGHT(ic) ;
12385
12386   FENTRY;
12387   
12388   /* if they are the same */
12389   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12390     return ;
12391
12392   /* reversed order operands are aopOp'ed so that result operand
12393    * is effective in case right is a stack symbol. This maneauver
12394    * allows to use the _G.resDirect flag later */
12395   pic16_aopOp(result,ic,TRUE);
12396   pic16_aopOp(right,ic,FALSE);
12397
12398   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12399
12400   /* if they are the same registers */
12401   if (pic16_sameRegs(AOP(right),AOP(result)))
12402     goto release;
12403
12404   /* if the result is a bit */
12405   if (AOP_TYPE(result) == AOP_CRY) {
12406     /* if the right size is a literal then
12407        we know what the value is */
12408     if (AOP_TYPE(right) == AOP_LIT) {
12409           
12410       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12411                   pic16_popGet(AOP(result),0));
12412
12413       if (((int) operandLitValue(right))) 
12414         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12415                        AOP(result)->aopu.aop_dir,
12416                        AOP(result)->aopu.aop_dir);
12417       else
12418         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12419                        AOP(result)->aopu.aop_dir,
12420                        AOP(result)->aopu.aop_dir);
12421       goto release;
12422     }
12423
12424     /* the right is also a bit variable */
12425     if (AOP_TYPE(right) == AOP_CRY) {
12426       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12427       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12428       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12429
12430       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12431                      AOP(result)->aopu.aop_dir,
12432                      AOP(result)->aopu.aop_dir);
12433       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12434                      AOP(right)->aopu.aop_dir,
12435                      AOP(right)->aopu.aop_dir);
12436       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12437                      AOP(result)->aopu.aop_dir,
12438                      AOP(result)->aopu.aop_dir);
12439       goto release ;
12440     }
12441
12442     /* we need to or */
12443     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12444     pic16_toBoolean(right);
12445     emitSKPZ;
12446     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12447     //pic16_aopPut(AOP(result),"a",0);
12448     goto release ;
12449   }
12450
12451   /* bit variables done */
12452   /* general case */
12453   size = AOP_SIZE(result);
12454   offset = 0 ;
12455
12456   if(AOP_TYPE(right) == AOP_LIT) {
12457         if(!IS_FLOAT(operandType( right )))
12458                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12459         else {
12460            union {
12461               unsigned long lit_int;
12462               float lit_float;
12463             } info;
12464         
12465                 /* take care if literal is a float */
12466                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12467                 lit = info.lit_int;
12468         }
12469   }
12470
12471 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12472 //                      sizeof(unsigned long int), sizeof(float));
12473
12474
12475   if (AOP_TYPE(right) == AOP_REG) {
12476     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12477     while (size--) {
12478       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12479     } // while
12480     goto release;
12481   }
12482
12483   /* when do we have to read the program memory?
12484    * - if right itself is a symbol in code space
12485    *   (we don't care what it points to if it's a pointer)
12486    * - AND right is not a function (we would want its address)
12487    */
12488   if(AOP_TYPE(right) != AOP_LIT
12489         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12490         && !IS_FUNC(OP_SYM_TYPE(right))
12491         && !IS_ITEMP(right))
12492   {
12493         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12494         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12495
12496         // set up table pointer
12497         if(is_LitOp(right)) {
12498 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12499                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12500                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12501                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12502                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12503                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12504                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12505         } else {
12506 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12507                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12508                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12509                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12510                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12511                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12512                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12513         }
12514
12515         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12516         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12517         while(size--) {
12518                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12519                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12520                         pic16_popGet(AOP(result),offset)));
12521                 offset++;
12522         }
12523
12524         /* FIXME: for pointers we need to extend differently (according
12525          * to pointer type DATA/CODE/EEPROM/... :*/
12526         size = getSize(OP_SYM_TYPE(right));
12527         if(AOP_SIZE(result) > size) {
12528                 size = AOP_SIZE(result) - size;
12529                 while(size--) {
12530                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12531                         offset++;
12532                 }
12533         }
12534         goto release;
12535   }
12536
12537
12538
12539 #if 0
12540 /* VR - What is this?! */
12541   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12542     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12543     if(aopIdx(AOP(result),0) == 4) {
12544
12545       /* this is a workaround to save value of right into wreg too,
12546        * value of wreg is going to be used later */
12547       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12548       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12549       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12550       goto release;
12551     } else
12552 //      assert(0);
12553       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12554   }
12555 #endif
12556
12557   know_W=-1;
12558   while (size--) {
12559   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12560     if(AOP_TYPE(right) == AOP_LIT) {
12561       if(lit&0xff) {
12562         if(know_W != (lit&0xff))
12563           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12564         know_W = lit&0xff;
12565         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12566       } else
12567         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12568
12569       lit >>= 8;
12570
12571     } else if (AOP_TYPE(right) == AOP_CRY) {
12572       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12573       if(offset == 0) {
12574         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12575         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12576         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12577       }
12578     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12579         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12580         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12581     } else {
12582       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12583
12584       if(!_G.resDirect)         /* use this aopForSym feature */
12585         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12586     }
12587             
12588     offset++;
12589   }
12590   
12591  release:
12592   pic16_freeAsmop (right,NULL,ic,FALSE);
12593   pic16_freeAsmop (result,NULL,ic,TRUE);
12594 }   
12595
12596 /*-----------------------------------------------------------------*/
12597 /* genJumpTab - generates code for jump table                       */
12598 /*-----------------------------------------------------------------*/
12599 static void genJumpTab (iCode *ic)
12600 {
12601   symbol *jtab;
12602   char *l;
12603   pCodeOp *jt_offs;
12604   pCodeOp *jt_offs_hi;
12605   pCodeOp *jt_label;
12606
12607     FENTRY;
12608
12609     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12610     /* get the condition into accumulator */
12611     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12612     MOVA(l);
12613     /* multiply by three */
12614     pic16_emitcode("add","a,acc");
12615     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12616
12617     jtab = newiTempLabel(NULL);
12618     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12619     pic16_emitcode("jmp","@a+dptr");
12620     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12621
12622 #if 0
12623     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12624     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12625     emitSKPNC;
12626     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12627     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12628     pic16_emitpLabel(jtab->key);
12629
12630 #else
12631
12632     jt_offs = pic16_popGetTempReg(0);
12633     jt_offs_hi = pic16_popGetTempReg(1);
12634     jt_label = pic16_popGetLabel (jtab->key);
12635     //fprintf (stderr, "Creating jump table...\n");
12636
12637     // calculate offset into jump table (idx * sizeof (GOTO))
12638     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12639     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12640     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12641     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12642     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12643     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12644     pic16_emitpcode(POC_MOVWF , jt_offs);
12645
12646     // prepare PCLATx (set to first entry in jump table)
12647     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12648     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12649     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12650     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12651     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12652
12653     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12654     pic16_emitpcode(POC_ADDWF , jt_offs);
12655     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12656     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12657     emitSKPNC;
12658     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12659
12660     // release temporaries and prepare jump into table (new PCL --> WREG)
12661     pic16_emitpcode(POC_MOVFW , jt_offs);
12662     pic16_popReleaseTempReg (jt_offs_hi, 1);
12663     pic16_popReleaseTempReg (jt_offs, 0);
12664
12665     // jump into the table
12666     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12667
12668     pic16_emitpLabelFORCE(jtab->key);
12669 #endif
12670
12671     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12672 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12673
12674     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12675     /* now generate the jump labels */
12676     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12677          jtab = setNextItem(IC_JTLABELS(ic))) {
12678 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12679         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12680         
12681     }
12682     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12683
12684 }
12685
12686 /*-----------------------------------------------------------------*/
12687 /* genMixedOperation - gen code for operators between mixed types  */
12688 /*-----------------------------------------------------------------*/
12689 /*
12690   TSD - Written for the PIC port - but this unfortunately is buggy.
12691   This routine is good in that it is able to efficiently promote 
12692   types to different (larger) sizes. Unfortunately, the temporary
12693   variables that are optimized out by this routine are sometimes
12694   used in other places. So until I know how to really parse the 
12695   iCode tree, I'm going to not be using this routine :(.
12696 */
12697 static int genMixedOperation (iCode *ic)
12698 {
12699 #if 0
12700   operand *result = IC_RESULT(ic);
12701   sym_link *ctype = operandType(IC_LEFT(ic));
12702   operand *right = IC_RIGHT(ic);
12703   int ret = 0;
12704   int big,small;
12705   int offset;
12706
12707   iCode *nextic;
12708   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12709
12710   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12711
12712   nextic = ic->next;
12713   if(!nextic)
12714     return 0;
12715
12716   nextright = IC_RIGHT(nextic);
12717   nextleft  = IC_LEFT(nextic);
12718   nextresult = IC_RESULT(nextic);
12719
12720   pic16_aopOp(right,ic,FALSE);
12721   pic16_aopOp(result,ic,FALSE);
12722   pic16_aopOp(nextright,  nextic, FALSE);
12723   pic16_aopOp(nextleft,   nextic, FALSE);
12724   pic16_aopOp(nextresult, nextic, FALSE);
12725
12726   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12727
12728     operand *t = right;
12729     right = nextright;
12730     nextright = t; 
12731
12732     pic16_emitcode(";remove right +","");
12733
12734   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12735 /*
12736     operand *t = right;
12737     right = nextleft;
12738     nextleft = t; 
12739 */
12740     pic16_emitcode(";remove left +","");
12741   } else
12742     return 0;
12743
12744   big = AOP_SIZE(nextleft);
12745   small = AOP_SIZE(nextright);
12746
12747   switch(nextic->op) {
12748
12749   case '+':
12750     pic16_emitcode(";optimize a +","");
12751     /* if unsigned or not an integral type */
12752     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12753       pic16_emitcode(";add a bit to something","");
12754     } else {
12755
12756       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12757
12758       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12759         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12760         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12761       } else
12762         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12763
12764       offset = 0;
12765       while(--big) {
12766
12767         offset++;
12768
12769         if(--small) {
12770           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12771             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12772             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12773           }
12774
12775           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12776           emitSKPNC;
12777           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12778                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12779                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12780           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12781           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12782
12783         } else {
12784           pic16_emitcode("rlf","known_zero,w");
12785
12786           /*
12787             if right is signed
12788               btfsc  right,7
12789                addlw ff
12790           */
12791           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12792             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12793             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12794           } else {
12795             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12796           }
12797         }
12798       }
12799       ret = 1;
12800     }
12801   }
12802   ret = 1;
12803
12804 release:
12805   pic16_freeAsmop(right,NULL,ic,TRUE);
12806   pic16_freeAsmop(result,NULL,ic,TRUE);
12807   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12808   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12809   if(ret)
12810     nextic->generated = 1;
12811
12812   return ret;
12813 #else
12814   return 0;
12815 #endif
12816 }
12817 /*-----------------------------------------------------------------*/
12818 /* genCast - gen code for casting                                  */
12819 /*-----------------------------------------------------------------*/
12820 static void genCast (iCode *ic)
12821 {
12822   operand *result = IC_RESULT(ic);
12823   sym_link *ctype = operandType(IC_LEFT(ic));
12824   sym_link *rtype = operandType(IC_RIGHT(ic));
12825   sym_link *restype = operandType(IC_RESULT(ic));
12826   operand *right = IC_RIGHT(ic);
12827   int size, offset ;
12828
12829
12830     FENTRY;
12831
12832         /* if they are equivalent then do nothing */
12833 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12834 //              return ;
12835
12836         pic16_aopOp(result,ic,FALSE);
12837         pic16_aopOp(right,ic,FALSE) ;
12838
12839         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12840
12841
12842         /* if the result is a bit */
12843         if (AOP_TYPE(result) == AOP_CRY) {
12844         
12845                 /* if the right size is a literal then
12846                  * we know what the value is */
12847                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12848
12849                 if (AOP_TYPE(right) == AOP_LIT) {
12850                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12851                                 pic16_popGet(AOP(result),0));
12852
12853                         if (((int) operandLitValue(right))) 
12854                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12855                                         AOP(result)->aopu.aop_dir,
12856                                         AOP(result)->aopu.aop_dir);
12857                         else
12858                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12859                                         AOP(result)->aopu.aop_dir,
12860                                         AOP(result)->aopu.aop_dir);
12861                         goto release;
12862                 }
12863
12864                 /* the right is also a bit variable */
12865                 if (AOP_TYPE(right) == AOP_CRY) {
12866                         emitCLRC;
12867                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12868
12869                         pic16_emitcode("clrc","");
12870                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12871                                 AOP(right)->aopu.aop_dir,
12872                                 AOP(right)->aopu.aop_dir);
12873                         pic16_aopPut(AOP(result),"c",0);
12874                         goto release ;
12875                 }
12876
12877                 /* we need to or */
12878                 if (AOP_TYPE(right) == AOP_REG) {
12879                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12880                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12881                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12882                 }
12883                 pic16_toBoolean(right);
12884                 pic16_aopPut(AOP(result),"a",0);
12885                 goto release ;
12886         }
12887
12888         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12889           int offset = 1;
12890
12891                 size = AOP_SIZE(result);
12892
12893                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12894
12895                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12896                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12897                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12898
12899                 while (size--)
12900                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12901
12902                 goto release;
12903         }
12904
12905         if(IS_BITFIELD(getSpec(restype))
12906           && IS_BITFIELD(getSpec(rtype))) {
12907           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12908         }
12909
12910         /* if they are the same size : or less */
12911         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12912
12913                 /* if they are in the same place */
12914                 if (pic16_sameRegs(AOP(right),AOP(result)))
12915                         goto release;
12916
12917                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12918 #if 0
12919                 if (IS_PTR_CONST(rtype))
12920 #else
12921                 if (IS_CODEPTR(rtype))
12922 #endif
12923                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12924
12925 #if 0
12926                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12927 #else
12928                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12929 #endif
12930                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12931
12932 #if 0
12933                 if(AOP_TYPE(right) == AOP_IMMD) {
12934                   pCodeOp *pcop0, *pcop1, *pcop2;
12935                   symbol *sym = OP_SYMBOL( right );
12936
12937                         size = AOP_SIZE(result);
12938                         /* low */
12939                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12940                         /* high */
12941                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12942                         /* upper */
12943                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12944         
12945                         if (size == 3) {
12946                                 pic16_emitpcode(POC_MOVLW, pcop0);
12947                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12948                                 pic16_emitpcode(POC_MOVLW, pcop1);
12949                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12950                                 pic16_emitpcode(POC_MOVLW, pcop2);
12951                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12952                         } else
12953                         if (size == 2) {
12954                                 pic16_emitpcode(POC_MOVLW, pcop0);
12955                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12956                                 pic16_emitpcode(POC_MOVLW, pcop1);
12957                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12958                         } else {
12959                                 pic16_emitpcode(POC_MOVLW, pcop0);
12960                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12961                         }
12962                 } else
12963 #endif
12964                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12965                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12966                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12967                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12968                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12969                         if(AOP_SIZE(result) <2)
12970                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12971                 } else {
12972                         /* if they in different places then copy */
12973                         size = AOP_SIZE(result);
12974                         offset = 0 ;
12975                         while (size--) {
12976                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12977                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12978                                 offset++;
12979                         }
12980                 }
12981                 goto release;
12982         }
12983
12984         /* if the result is of type pointer */
12985         if (IS_PTR(ctype)) {
12986           int p_type;
12987           sym_link *type = operandType(right);
12988           sym_link *etype = getSpec(type);
12989
12990                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12991
12992                 /* pointer to generic pointer */
12993                 if (IS_GENPTR(ctype)) {
12994                   char *l = zero;
12995             
12996                         if (IS_PTR(type)) 
12997                                 p_type = DCL_TYPE(type);
12998                         else {
12999                 /* we have to go by the storage class */
13000                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13001
13002 /*              if (SPEC_OCLS(etype)->codesp )  */
13003 /*                  p_type = CPOINTER ;  */
13004 /*              else */
13005 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13006 /*                      p_type = FPOINTER ; */
13007 /*                  else */
13008 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13009 /*                          p_type = PPOINTER; */
13010 /*                      else */
13011 /*                          if (SPEC_OCLS(etype) == idata ) */
13012 /*                              p_type = IPOINTER ; */
13013 /*                          else */
13014 /*                              p_type = POINTER ; */
13015             }
13016                 
13017             /* the first two bytes are known */
13018       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13019             size = GPTRSIZE - 1; 
13020             offset = 0 ;
13021             while (size--) {
13022               if(offset < AOP_SIZE(right)) {
13023                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13024                 pic16_mov2f(AOP(result), AOP(right), offset);
13025 /*
13026                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13027                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13028                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13029                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13030                 } else { 
13031                   
13032                   pic16_aopPut(AOP(result),
13033                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13034                          offset);
13035                 }
13036 */
13037               } else 
13038                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13039               offset++;
13040             }
13041             /* the last byte depending on type */
13042             switch (p_type) {
13043             case IPOINTER:
13044             case POINTER:
13045                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13046                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13047 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13048                 break;
13049
13050             case CPOINTER:
13051                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13052                 break;
13053
13054             case FPOINTER:
13055               pic16_emitcode(";BUG!? ","%d",__LINE__);
13056                 l = one;
13057                 break;
13058             case PPOINTER:
13059               pic16_emitcode(";BUG!? ","%d",__LINE__);
13060                 l = "#0x03";
13061                 break;
13062
13063             case GPOINTER:
13064                 if (GPTRSIZE > AOP_SIZE(right)) {
13065                   // assume data pointer... THIS MIGHT BE WRONG!
13066                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13067                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13068                 } else {
13069                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13070                 }
13071               break;
13072               
13073             default:
13074                 /* this should never happen */
13075                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13076                        "got unknown pointer type");
13077                 exit(1);
13078             }
13079             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13080             goto release ;
13081         }
13082         
13083         
13084         assert( 0 );
13085         /* just copy the pointers */
13086         size = AOP_SIZE(result);
13087         offset = 0 ;
13088         while (size--) {
13089             pic16_aopPut(AOP(result),
13090                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13091                    offset);
13092             offset++;
13093         }
13094         goto release ;
13095     }
13096     
13097
13098
13099     /* so we now know that the size of destination is greater
13100     than the size of the source.
13101     Now, if the next iCode is an operator then we might be
13102     able to optimize the operation without performing a cast.
13103     */
13104     if(genMixedOperation(ic))
13105       goto release;
13106
13107     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13108     
13109     /* we move to result for the size of source */
13110     size = AOP_SIZE(right);
13111     offset = 0 ;
13112
13113     while (size--) {
13114       if(!_G.resDirect)
13115         pic16_mov2f(AOP(result), AOP(right), offset);
13116       offset++;
13117     }
13118
13119     /* now depending on the sign of the destination */
13120     size = AOP_SIZE(result) - AOP_SIZE(right);
13121     /* if unsigned or not an integral type */
13122     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13123       while (size--)
13124         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13125     } else {
13126       /* we need to extend the sign :( */
13127
13128       if(size == 1) {
13129         /* Save one instruction of casting char to int */
13130         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13131         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13132         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13133       } else {
13134         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13135
13136         if(offset)
13137           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13138         else
13139           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13140         
13141         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13142
13143         while (size--)
13144           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13145       }
13146     }
13147
13148 release:
13149     pic16_freeAsmop(right,NULL,ic,TRUE);
13150     pic16_freeAsmop(result,NULL,ic,TRUE);
13151
13152 }
13153
13154 /*-----------------------------------------------------------------*/
13155 /* genDjnz - generate decrement & jump if not zero instrucion      */
13156 /*-----------------------------------------------------------------*/
13157 static int genDjnz (iCode *ic, iCode *ifx)
13158 {
13159     symbol *lbl, *lbl1;
13160     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13161
13162     if (!ifx)
13163         return 0;
13164     
13165     /* if the if condition has a false label
13166        then we cannot save */
13167     if (IC_FALSE(ifx))
13168         return 0;
13169
13170     /* if the minus is not of the form 
13171        a = a - 1 */
13172     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13173         !IS_OP_LITERAL(IC_RIGHT(ic)))
13174         return 0;
13175
13176     if (operandLitValue(IC_RIGHT(ic)) != 1)
13177         return 0;
13178
13179     /* if the size of this greater than one then no
13180        saving */
13181     if (getSize(operandType(IC_RESULT(ic))) > 1)
13182         return 0;
13183
13184     /* otherwise we can save BIG */
13185     lbl = newiTempLabel(NULL);
13186     lbl1= newiTempLabel(NULL);
13187
13188     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13189     
13190     if (IS_AOP_PREG(IC_RESULT(ic))) {
13191         pic16_emitcode("dec","%s",
13192                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13193         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13194         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13195     } else {    
13196
13197
13198       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13199       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13200
13201       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13202       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13203
13204     }
13205     
13206     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13207     ifx->generated = 1;
13208     return 1;
13209 }
13210
13211 /*-----------------------------------------------------------------*/
13212 /* genReceive - generate code for a receive iCode                  */
13213 /*-----------------------------------------------------------------*/
13214 static void genReceive (iCode *ic)
13215 {    
13216
13217   FENTRY;
13218
13219 #if 0
13220   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13221         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13222 #endif
13223 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13224
13225   if (isOperandInFarSpace(IC_RESULT(ic))
13226       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13227           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13228
13229     int size = getSize(operandType(IC_RESULT(ic)));
13230     int offset =  pic16_fReturnSizePic - size;
13231
13232       assert( 0 );
13233       while (size--) {
13234         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13235                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13236                       offset++;
13237         }
13238
13239       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13240
13241       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13242       size = AOP_SIZE(IC_RESULT(ic));
13243       offset = 0;
13244       while (size--) {
13245         pic16_emitcode ("pop","acc");
13246         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13247       }
13248   } else {
13249     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13250     _G.accInUse++;
13251     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13252     _G.accInUse--;
13253
13254     /* set pseudo stack pointer to where it should be - dw*/
13255     GpsuedoStkPtr = ic->parmBytes;
13256
13257     /* setting GpsuedoStkPtr has side effects here: */
13258     assignResultValue(IC_RESULT(ic), 0);
13259   }
13260
13261   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13262 }
13263
13264 /*-----------------------------------------------------------------*/
13265 /* genDummyRead - generate code for dummy read of volatiles        */
13266 /*-----------------------------------------------------------------*/
13267 static void
13268 genDummyRead (iCode * ic)
13269 {
13270   operand *op;
13271   int i;
13272
13273   op = IC_RIGHT(ic);
13274   if (op && IS_SYMOP(op)) {
13275     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13276       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13277       return;
13278     }
13279     pic16_aopOp (op, ic, FALSE);
13280     for (i=0; i < AOP_SIZE(op); i++) {
13281       // may need to protect this from the peepholer -- this is not nice but works...
13282       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13283       pic16_mov2w (AOP(op),i);
13284       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13285     } // for i
13286     pic16_freeAsmop (op, NULL, ic, TRUE);
13287   } else if (op) {
13288     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13289   } // if
13290 }
13291
13292 /*-----------------------------------------------------------------*/
13293 /* genpic16Code - generate code for pic16 based controllers        */
13294 /*-----------------------------------------------------------------*/
13295 /*
13296  * At this point, ralloc.c has gone through the iCode and attempted
13297  * to optimize in a way suitable for a PIC. Now we've got to generate
13298  * PIC instructions that correspond to the iCode.
13299  *
13300  * Once the instructions are generated, we'll pass through both the
13301  * peep hole optimizer and the pCode optimizer.
13302  *-----------------------------------------------------------------*/
13303
13304 void genpic16Code (iCode *lic)
13305 {
13306   iCode *ic;
13307   int cln = 0;
13308
13309     lineHead = lineCurr = NULL;
13310
13311     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13312     pic16_addpBlock(pb);
13313
13314 #if 0
13315     /* if debug information required */
13316     if (options.debug && currFunc) {
13317       if (currFunc) {
13318         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13319       }
13320     }
13321 #endif
13322
13323     for (ic = lic ; ic ; ic = ic->next ) {
13324
13325       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13326       if ( cln != ic->lineno ) {
13327         if ( options.debug ) {
13328           debugFile->writeCLine (ic);
13329         }
13330         
13331         if(!options.noCcodeInAsm) {
13332           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13333               printCLine(ic->filename, ic->lineno)));
13334         }
13335
13336         cln = ic->lineno ;
13337       }
13338         
13339       if(options.iCodeInAsm) {
13340         char *l;
13341
13342           /* insert here code to print iCode as comment */
13343           l = Safe_strdup(printILine(ic));
13344           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13345       }
13346         
13347       /* if the result is marked as
13348        * spilt and rematerializable or code for
13349        * this has already been generated then
13350        * do nothing */
13351       if (resultRemat(ic) || ic->generated ) 
13352         continue ;
13353         
13354       /* depending on the operation */
13355       switch (ic->op) {
13356         case '!' :
13357           pic16_genNot(ic);
13358           break;
13359             
13360         case '~' :
13361           pic16_genCpl(ic);
13362           break;
13363             
13364         case UNARYMINUS:
13365           genUminus (ic);
13366           break;
13367             
13368         case IPUSH:
13369           genIpush (ic);
13370           break;
13371             
13372         case IPOP:
13373           /* IPOP happens only when trying to restore a 
13374            * spilt live range, if there is an ifx statement
13375            * following this pop then the if statement might
13376            * be using some of the registers being popped which
13377            * would destroy the contents of the register so
13378            * we need to check for this condition and handle it */
13379            if (ic->next
13380              && ic->next->op == IFX
13381              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13382                genIfx (ic->next,ic);
13383           else
13384             genIpop (ic);
13385           break; 
13386             
13387         case CALL:
13388           genCall (ic);
13389           break;
13390             
13391         case PCALL:
13392           genPcall (ic);
13393           break;
13394             
13395         case FUNCTION:
13396           genFunction (ic);
13397           break;
13398             
13399         case ENDFUNCTION:
13400           genEndFunction (ic);
13401           break;
13402             
13403         case RETURN:
13404           genRet (ic);
13405           break;
13406             
13407         case LABEL:
13408           genLabel (ic);
13409           break;
13410             
13411         case GOTO:
13412           genGoto (ic);
13413           break;
13414             
13415         case '+' :
13416           pic16_genPlus (ic) ;
13417           break;
13418             
13419         case '-' :
13420           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13421             pic16_genMinus (ic);
13422           break;
13423
13424         case '*' :
13425           genMult (ic);
13426           break;
13427             
13428         case '/' :
13429           genDiv (ic) ;
13430           break;
13431             
13432         case '%' :
13433           genMod (ic);
13434           break;
13435             
13436         case '>' :
13437           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13438           break;
13439             
13440         case '<' :
13441           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13442           break;
13443             
13444         case LE_OP:
13445         case GE_OP:
13446         case NE_OP:
13447           /* note these two are xlated by algebraic equivalence
13448            * during parsing SDCC.y */
13449           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13450             "got '>=' or '<=' shouldn't have come here");
13451           break;
13452
13453         case EQ_OP:
13454           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13455           break;            
13456             
13457         case AND_OP:
13458           genAndOp (ic);
13459           break;
13460             
13461         case OR_OP:
13462           genOrOp (ic);
13463           break;
13464             
13465         case '^' :
13466           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13467           break;
13468             
13469         case '|' :
13470           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13471           break;
13472             
13473         case BITWISEAND:
13474           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13475           break;
13476             
13477         case INLINEASM:
13478           genInline (ic);
13479           break;
13480             
13481         case RRC:
13482           genRRC (ic);
13483           break;
13484             
13485         case RLC:
13486           genRLC (ic);
13487           break;
13488             
13489         case GETHBIT:
13490           genGetHbit (ic);
13491           break;
13492             
13493         case LEFT_OP:
13494           genLeftShift (ic);
13495           break;
13496             
13497         case RIGHT_OP:
13498           genRightShift (ic);
13499           break;
13500             
13501         case GET_VALUE_AT_ADDRESS:
13502           genPointerGet(ic);
13503           break;
13504             
13505         case '=' :
13506           if (POINTER_SET(ic))
13507             genPointerSet(ic);
13508           else
13509             genAssign(ic);
13510           break;
13511             
13512         case IFX:
13513           genIfx (ic,NULL);
13514           break;
13515             
13516         case ADDRESS_OF:
13517           genAddrOf (ic);
13518           break;
13519             
13520         case JUMPTABLE:
13521           genJumpTab (ic);
13522           break;
13523             
13524         case CAST:
13525           genCast (ic);
13526           break;
13527             
13528         case RECEIVE:
13529           genReceive(ic);
13530           break;
13531             
13532         case SEND:
13533           addSet(&_G.sendSet,ic);
13534           break;
13535
13536         case DUMMY_READ_VOLATILE:
13537           genDummyRead (ic);
13538           break;
13539
13540         default :
13541           ic = ic;
13542       }
13543     }
13544
13545
13546     /* now we are ready to call the
13547        peep hole optimizer */
13548     if (!options.nopeep)
13549       peepHole (&lineHead);
13550
13551     /* now do the actual printing */
13552     printLine (lineHead, codeOutFile);
13553
13554 #ifdef PCODE_DEBUG
13555     DFPRINTF((stderr,"printing pBlock\n\n"));
13556     pic16_printpBlock(stdout,pb);
13557 #endif
13558
13559     return;
13560 }
13561