* device/lib/pic16/startup/crt0i.c (_cinit): local variables where
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 /* Set the following to 1 to enable the slower/bigger
51  * but more robust generic shifting routine (which also
52  * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
54
55 /* Set the following to 1 to enable the new
56  * stripped down genCmp version.
57  * This version should be easier to understand,
58  * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
60
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
141
142 static char *accUse[] = {"WREG"};
143
144 //static short rbank = -1;
145
146 static struct {
147     short r0Pushed;
148     short r1Pushed;
149     short fsr0Pushed;
150     short accInUse;
151     short inLine;
152     short debugLine;
153     short nRegsSaved;
154     short ipushRegs;
155     set *sendSet;
156     set *stackRegSet;
157     int usefastretfie;
158     bitVect *fregsUsed;                 /* registers used in function */
159     bitVect *sregsAlloc;
160     set *sregsAllocSet;                 /* registers used to store stack variables */
161     int stack_lat;                      /* stack offset latency */
162     int resDirect;
163     int useWreg;                        /* flag when WREG is used to pass function parameter */
164 } _G;
165
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
170
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
173
174 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
178
179 static  pBlock *pb;
180
181 /*-----------------------------------------------------------------*/
182 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
183 /*                 exponent of 2 is returned, otherwise -1 is      */
184 /*                 returned.                                       */
185 /* note that this is similar to the function `powof2' in SDCCsymt  */
186 /* if(n == 2^y)                                                    */
187 /*   return y;                                                     */
188 /* return -1;                                                      */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
191 {
192   if(num) {
193     if( (num & (num-1)) == 0) {
194       int nshifts = -1;
195       while(num) {
196         num>>=1;
197         nshifts++;
198       }
199       return nshifts;
200     }
201   }
202
203   return -1;
204 }
205
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
207 {
208   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
209                        line_no,
210                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
213                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
215                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216                        ((result) ? AOP_SIZE(result) : 0));
217 }
218
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
220 {
221
222   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
223                        line_no,
224                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
227                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
228                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
229                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
230
231 }
232
233 void pic16_emitpcomment (char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     va_start(ap,fmt);   
240
241     lb[0] = ';';
242     vsprintf(lb+1,fmt,ap);
243
244     while (isspace(*lbp)) lbp++;
245
246     if (lbp && *lbp) 
247         lineCurr = (lineCurr ?
248                     connectLine(lineCurr,newLineNode(lb)) :
249                     (lineHead = newLineNode(lb)));
250     lineCurr->isInline = _G.inLine;
251     lineCurr->isDebug  = _G.debugLine;
252
253     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
254     va_end(ap);
255
256 //      fprintf(stderr, "%s\n", lb);
257 }
258
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
260 {
261     va_list ap;
262     char lb[INITIAL_INLINEASM];  
263     char *lbp = lb;
264
265     if(!pic16_debug_verbose)
266       return;
267
268     va_start(ap,fmt);   
269
270     if (inst && *inst) {
271         if (fmt && *fmt)
272             sprintf(lb,"%s\t",inst);
273         else
274             sprintf(lb,"%s",inst);
275         vsprintf(lb+(strlen(lb)),fmt,ap);
276     }  else
277         vsprintf(lb,fmt,ap);
278
279     while (isspace(*lbp)) lbp++;
280
281     if (lbp && *lbp) 
282         lineCurr = (lineCurr ?
283                     connectLine(lineCurr,newLineNode(lb)) :
284                     (lineHead = newLineNode(lb)));
285     lineCurr->isInline = _G.inLine;
286     lineCurr->isDebug  = _G.debugLine;
287
288     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
289     va_end(ap);
290
291 //      fprintf(stderr, "%s\n", lb);
292 }
293
294
295
296 void pic16_emitpLabel(int key)
297 {
298   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
299 }
300
301 void pic16_emitpLabelFORCE(int key)
302 {
303   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
304 }
305
306 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
307 {
308
309   if(pcop)
310     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
311   else
312     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
313 }
314
315 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
316 {
317   if(pcop)
318     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
319   else
320     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
321 }
322   
323 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
324 {
325
326   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
327
328 }
329
330
331 #if 1
332 #define pic16_emitcode  DEBUGpic16_emitcode
333 #else
334 /*-----------------------------------------------------------------*/
335 /* pic16_emitcode - writes the code into a file : for now it is simple    */
336 /*-----------------------------------------------------------------*/
337 void pic16_emitcode (char *inst,char *fmt, ...)
338 {
339     va_list ap;
340     char lb[INITIAL_INLINEASM];  
341     char *lbp = lb;
342
343     va_start(ap,fmt);   
344
345     if (inst && *inst) {
346         if (fmt && *fmt)
347             sprintf(lb,"%s\t",inst);
348         else
349             sprintf(lb,"%s",inst);
350         vsprintf(lb+(strlen(lb)),fmt,ap);
351     }  else
352         vsprintf(lb,fmt,ap);
353
354     while (isspace(*lbp)) lbp++;
355
356     if (lbp && *lbp) 
357         lineCurr = (lineCurr ?
358                     connectLine(lineCurr,newLineNode(lb)) :
359                     (lineHead = newLineNode(lb)));
360     lineCurr->isInline = _G.inLine;
361     lineCurr->isDebug  = _G.debugLine;
362
363 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
364
365 //    if(pic16_debug_verbose)
366 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
367
368     va_end(ap);
369 }
370 #endif
371
372
373 /*-----------------------------------------------------------------*/
374 /* pic16_emitDebuggerSymbol - associate the current code location  */
375 /*   with a debugger symbol                                        */
376 /*-----------------------------------------------------------------*/
377 void
378 pic16_emitDebuggerSymbol (char * debugSym)
379 {
380   _G.debugLine = 1;
381   pic16_emitcode (";", "%s ==.", debugSym);
382   _G.debugLine = 0;
383 }
384
385
386 /*-----------------------------------------------------------------*/
387 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
388 /*-----------------------------------------------------------------*/
389 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
390 {
391 //    bool r0iu = FALSE , r1iu = FALSE;
392 //    bool r0ou = FALSE , r1ou = FALSE;
393     bool fsr0iu = FALSE, fsr0ou;
394     bool fsr2iu = FALSE, fsr2ou;
395     
396     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
397
398     
399     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
400     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
401     
402     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
403     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
404
405     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
406         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
407         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
408     }
409
410     if(!fsr0iu && !fsr0ou) {
411         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
412         (*aopp)->type = AOP_FSR0;
413
414         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
415         
416       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
417     }
418
419 #if 0
420     /* no usage of FSR2 */
421     if(!fsr2iu && !fsr2ou) {
422         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
423         (*aopp)->type = AOP_FSR2;
424
425       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
426     }
427 #endif
428         
429     /* now we know they both have usage */
430     /* if fsr0 not used in this instruction */
431     if (!fsr0iu) {
432         if (!_G.fsr0Pushed) {
433                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
434                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
435                 _G.fsr0Pushed++;
436         }
437
438         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
439         (*aopp)->type = AOP_FSR0;
440
441 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
442
443       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
444     }
445         
446
447     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
448     assert( 0 );
449
450     return NULL;
451 #if 0
452     /* the logic: if r0 & r1 used in the instruction
453     then we are in trouble otherwise */
454
455     /* first check if r0 & r1 are used by this
456     instruction, in which case we are in trouble */
457     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
458         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
459     {
460         goto endOfWorld;      
461     }
462
463     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
464     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
465
466     /* if no usage of r0 then return it */
467     if (!r0iu && !r0ou) {
468         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
469         (*aopp)->type = AOP_R0; 
470         
471         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
472     }
473
474     /* if no usage of r1 then return it */
475     if (!r1iu && !r1ou) {
476         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477         (*aopp)->type = AOP_R1;
478
479         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
480     }    
481
482     /* now we know they both have usage */
483     /* if r0 not used in this instruction */
484     if (!r0iu) {
485         /* push it if not already pushed */
486         if (!_G.r0Pushed) {
487           //pic16_emitcode ("push","%s",
488           //          pic16_regWithIdx(R0_IDX)->dname);
489             _G.r0Pushed++ ;
490         }
491         
492         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
493         (*aopp)->type = AOP_R0;
494
495         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
496     }
497
498     /* if r1 not used then */
499
500     if (!r1iu) {
501         /* push it if not already pushed */
502         if (!_G.r1Pushed) {
503           //pic16_emitcode ("push","%s",
504           //          pic16_regWithIdx(R1_IDX)->dname);
505             _G.r1Pushed++ ;
506         }
507         
508         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
509         (*aopp)->type = AOP_R1;
510         return pic16_regWithIdx(R1_IDX);
511     }
512
513 endOfWorld :
514     /* I said end of world but not quite end of world yet */
515     /* if this is a result then we can push it on the stack*/
516     if (result) {
517         (*aopp)->type = AOP_STK;    
518         return NULL;
519     }
520
521     /* other wise this is true end of the world */
522     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
523            "getFreePtr should never reach here");
524     exit(0);
525 #endif
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* newAsmop - creates a new asmOp                                  */
530 /*-----------------------------------------------------------------*/
531 static asmop *newAsmop (short type)
532 {
533     asmop *aop;
534
535     aop = Safe_calloc(1,sizeof(asmop));
536     aop->type = type;
537     return aop;
538 }
539
540 static void genSetDPTR(int n)
541 {
542     if (!n)
543     {
544         pic16_emitcode(";", "Select standard DPTR");
545         pic16_emitcode("mov", "dps, #0x00");
546     }
547     else
548     {
549         pic16_emitcode(";", "Select alternate DPTR");
550         pic16_emitcode("mov", "dps, #0x01");
551     }
552 }
553
554 /*-----------------------------------------------------------------*/
555 /* resolveIfx - converts an iCode ifx into a form more useful for  */
556 /*              generating code                                    */
557 /*-----------------------------------------------------------------*/
558 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
559 {
560   FENTRY2;
561   
562 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
563
564   if(!resIfx) 
565     return;
566
567
568   resIfx->condition = 1;    /* assume that the ifx is true */
569   resIfx->generated = 0;    /* indicate that the ifx has not been used */
570
571   if(!ifx) {
572     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
573
574 #if 1
575     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
576                         __FUNCTION__,__LINE__,resIfx->lbl->key);
577 #endif
578
579   } else {
580     if(IC_TRUE(ifx)) {
581       resIfx->lbl = IC_TRUE(ifx);
582     } else {
583       resIfx->lbl = IC_FALSE(ifx);
584       resIfx->condition = 0;
585     }
586
587 #if 1
588     if(IC_TRUE(ifx)) 
589       DEBUGpic16_emitcode("; +++","ifx true is non-null");
590     else
591       DEBUGpic16_emitcode("; +++","ifx true is null");
592     if(IC_FALSE(ifx)) 
593       DEBUGpic16_emitcode("; +++","ifx false is non-null");
594     else
595       DEBUGpic16_emitcode("; +++","ifx false is null");
596 #endif
597   }
598
599   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
600
601 }
602 #if 0
603 /*-----------------------------------------------------------------*/
604 /* pointerCode - returns the code for a pointer type               */
605 /*-----------------------------------------------------------------*/
606 static int pointerCode (sym_link *etype)
607 {
608
609     return PTR_TYPE(SPEC_OCLS(etype));
610
611 }
612 #endif
613
614 /*-----------------------------------------------------------------*/
615 /* aopForSym - for a true symbol                                   */
616 /*-----------------------------------------------------------------*/
617 static asmop *aopForSym (iCode *ic, operand *op, bool result)
618 {
619     symbol *sym=OP_SYMBOL(op);
620     asmop *aop;
621     memmap *space= SPEC_OCLS(sym->etype);
622
623     FENTRY2;
624     
625     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
626     
627 //    sym = OP_SYMBOL(op);
628
629     /* if already has one */
630     if (sym->aop) {
631             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
632         return sym->aop;
633     }
634
635 #if 0
636     /* if symbol was initially placed onStack then we must re-place it
637      * to direct memory, since pic16 does not have a specific stack */
638     if(sym->onStack) {
639         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
640     }
641 #endif
642
643
644 #if 0
645     if(sym->iaccess) {
646       if(space->paged) {
647         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
648
649         sym->aop = aop = newAsmop (AOP_PAGED);
650         aop->aopu.aop_dir = sym->rname ;
651         aop->size = getSize(sym->type);
652         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
653         pic16_allocDirReg( IC_LEFT(ic) );
654         return aop;
655       }
656       assert( 0 );
657     }
658 #endif
659     
660 #if 1
661     /* assign depending on the storage class */
662     /* if it is on the stack or indirectly addressable */
663     /* space we need to assign either r0 or r1 to it   */    
664     if (sym->onStack)   // || sym->iaccess)
665     {
666       pCodeOp *pcop[4];
667       int i;
668       
669         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
670                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
671         
672         /* acquire a temporary register -- it is saved in function */
673
674         sym->aop = aop = newAsmop(AOP_STA);
675         aop->aopu.stk.stk = sym->stack;
676         aop->size = getSize(sym->type);
677
678
679         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
680         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
681           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
682           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
683           
684           for(i=0;i<aop->size;i++)
685             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
686             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
687         } else
688         if(1 && ic->op == SEND) {
689
690           /* if SEND do the send here */
691           _G.resDirect = 1;
692         } else {
693           for(i=0;i<aop->size;i++) {
694             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
695             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
696           }
697         }
698
699
700 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
701
702 #if 1
703         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
704
705         // we do not need to load the value if it is to be defined...
706         if (result) return aop;
707
708         if(_G.accInUse) {
709                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
710         }
711         
712         for(i=0;i<aop->size;i++) {
713
714           /* initialise for stack access via frame pointer */
715           // operands on stack are accessible via "FSR2 + index" with index
716           // starting at 2 for arguments and growing from 0 downwards for
717           // local variables (index == 0 is not assigned so we add one here)
718           {
719             int soffs = sym->stack;
720             if (soffs <= 0) {
721               assert (soffs < 0);
722               soffs++;
723             } // if
724
725             if(1 && ic->op == SEND) {
726               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
727               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
728                     pic16_popCopyReg( pic16_frame_plusw ),
729                     pic16_popCopyReg(pic16_stack_postdec )));
730             } else {
731               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
732               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
733                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
734             }
735           }
736         }
737         
738         if(_G.accInUse) {
739                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
740         }
741         
742         return (aop);
743 #endif
744
745 #if 0
746         /* now assign the address of the variable to 
747         the pointer register */
748         if (aop->type != AOP_STK) {
749
750             if (sym->onStack) {
751                     if ( _G.accInUse )
752                         pic16_emitcode("push","acc");
753
754                     pic16_emitcode("mov","a,_bp");
755                     pic16_emitcode("add","a,#0x%02x",
756                              ((sym->stack < 0) ?
757                               ((char)(sym->stack - _G.nRegsSaved )) :
758                               ((char)sym->stack)) & 0xff);
759                     pic16_emitcode("mov","%s,a",
760                              aop->aopu.aop_ptr->name);
761
762                     if ( _G.accInUse )
763                         pic16_emitcode("pop","acc");
764             } else
765                 pic16_emitcode("mov","%s,#%s",
766                          aop->aopu.aop_ptr->name,
767                          sym->rname);
768             aop->paged = space->paged;
769         } else
770             aop->aopu.aop_stk = sym->stack;
771         return aop;
772 #endif
773
774     }
775 #endif
776
777 #if 0
778     if (sym->onStack && options.stack10bit)
779     {
780         /* It's on the 10 bit stack, which is located in
781          * far data space.
782          */
783          
784       //DEBUGpic16_emitcode(";","%d",__LINE__);
785
786         if ( _G.accInUse )
787                 pic16_emitcode("push","acc");
788
789         pic16_emitcode("mov","a,_bp");
790         pic16_emitcode("add","a,#0x%02x",
791                  ((sym->stack < 0) ?
792                    ((char)(sym->stack - _G.nRegsSaved )) :
793                    ((char)sym->stack)) & 0xff);
794         
795         genSetDPTR(1);
796         pic16_emitcode ("mov","dpx1,#0x40");
797         pic16_emitcode ("mov","dph1,#0x00");
798         pic16_emitcode ("mov","dpl1, a");
799         genSetDPTR(0);
800         
801         if ( _G.accInUse )
802             pic16_emitcode("pop","acc");
803             
804         sym->aop = aop = newAsmop(AOP_DPTR2);
805         aop->size = getSize(sym->type); 
806         return aop;
807     }
808 #endif
809
810 #if 1
811     /* special case for a function */
812     if (IS_FUNC(sym->type)) {   
813         sym->aop = aop = newAsmop(AOP_PCODE);
814         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
815         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
816         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
817         PCOI(aop->aopu.pcop)->index = 0;
818         aop->size = FPTRSIZE; 
819         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
820         return aop;
821     }
822 #endif
823
824
825
826     //DEBUGpic16_emitcode(";","%d",__LINE__);
827     /* if in bit space */
828     if (IN_BITSPACE(space)) {
829         sym->aop = aop = newAsmop (AOP_CRY);
830         aop->aopu.aop_dir = sym->rname ;
831         aop->size = getSize(sym->type);
832         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
833         return aop;
834     }
835     /* if it is in direct space */
836     if (IN_DIRSPACE(space)) {
837         sym->aop = aop = newAsmop (AOP_DIR);
838         aop->aopu.aop_dir = sym->rname ;
839         aop->size = getSize(sym->type);
840         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841         pic16_allocDirReg( IC_LEFT(ic) );
842         return aop;
843     }
844
845
846     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
847         sym->aop = aop = newAsmop (AOP_DIR);
848         aop->aopu.aop_dir = sym->rname ;
849         aop->size = getSize(sym->type);
850         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851         pic16_allocDirReg( IC_LEFT(ic) );
852         return aop;
853     }
854
855
856     /* only remaining is far space */
857     sym->aop = aop = newAsmop(AOP_PCODE);
858
859 /* change the next if to 1 to revert to good old immediate code */
860         if(IN_CODESPACE(space)) {
861                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
862                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
863                 PCOI(aop->aopu.pcop)->index = 0;
864         } else {
865                 /* try to allocate via direct register */
866                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
867 //              aop->size = getSize( sym->type );
868         }
869
870         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
871                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
872
873 #if 0
874         if(!pic16_allocDirReg (IC_LEFT(ic)))
875                 return NULL;
876 #endif
877
878         if(IN_DIRSPACE( space ))
879                 aop->size = PTRSIZE;
880         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
881                 aop->size = FPTRSIZE;
882         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
883         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
884         else if(sym->onStack) {
885                 aop->size = PTRSIZE;
886         } else {
887           if(SPEC_SCLS(sym->etype) == S_PDATA) {
888             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
889             aop->size = FPTRSIZE;
890           } else
891                 assert( 0 );
892         }
893
894     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
895
896     /* if it is in code space */
897     if (IN_CODESPACE(space))
898         aop->code = 1;
899
900     return aop;     
901 }
902
903 /*-----------------------------------------------------------------*/
904 /* aopForRemat - rematerialzes an object                           */
905 /*-----------------------------------------------------------------*/
906 static asmop *aopForRemat (operand *op) // x symbol *sym)
907 {
908   symbol *sym = OP_SYMBOL(op);
909   operand *refop;
910   iCode *ic = NULL, *oldic;
911   asmop *aop = newAsmop(AOP_PCODE);
912   int val = 0;
913   int offset = 0;
914   int viaimmd=0;
915
916     FENTRY2;
917     
918         ic = sym->rematiCode;
919
920         if(IS_OP_POINTER(op)) {
921                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
922         }
923
924         for (;;) {
925                 oldic = ic;
926
927 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
928         
929                 if (ic->op == '+') {
930                         val += (int) operandLitValue(IC_RIGHT(ic));
931                 } else if (ic->op == '-') {
932                         val -= (int) operandLitValue(IC_RIGHT(ic));
933                 } else
934                         break;
935                 
936                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
937         }
938
939         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
940         refop = IC_LEFT(ic);
941
942         if(!op->isaddr)viaimmd++; else viaimmd=0;
943                 
944 /* set the following if to 1 to revert to good old immediate code */
945         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
946                 || viaimmd) {
947
948                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
949
950                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
951
952 #if 0
953                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
954 #else
955                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
956 #endif
957
958                 PCOI(aop->aopu.pcop)->index = val;
959                 
960                 aop->size = getSize( sym->type );
961         } else {
962                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
963
964                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
965                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
966
967                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
968         }
969
970
971         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
972                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
973 #if 0
974                 val, IS_PTR_CONST(operandType(op)));
975 #else
976                 val, IS_CODEPTR(operandType(op)));
977 #endif
978
979 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
980
981         pic16_allocDirReg (IC_LEFT(ic));
982
983         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
984                 aop->code = 1;
985
986   return aop;        
987 }
988
989 #if 0
990 static int aopIdx (asmop *aop, int offset)
991 {
992   if(!aop)
993     return -1;
994
995   if(aop->type !=  AOP_REG)
996     return -2;
997         
998   return aop->aopu.aop_reg[offset]->rIdx;
999
1000 }
1001 #endif
1002
1003 /*-----------------------------------------------------------------*/
1004 /* regsInCommon - two operands have some registers in common       */
1005 /*-----------------------------------------------------------------*/
1006 static bool regsInCommon (operand *op1, operand *op2)
1007 {
1008     symbol *sym1, *sym2;
1009     int i;
1010
1011     /* if they have registers in common */
1012     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1013         return FALSE ;
1014
1015     sym1 = OP_SYMBOL(op1);
1016     sym2 = OP_SYMBOL(op2);
1017
1018     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1019         return FALSE ;
1020
1021     for (i = 0 ; i < sym1->nRegs ; i++) {
1022         int j;
1023         if (!sym1->regs[i])
1024             continue ;
1025
1026         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1027             if (!sym2->regs[j])
1028                 continue ;
1029
1030             if (sym2->regs[j] == sym1->regs[i])
1031                 return TRUE ;
1032         }
1033     }
1034
1035     return FALSE ;
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* operandsEqu - equivalent                                        */
1040 /*-----------------------------------------------------------------*/
1041 static bool operandsEqu ( operand *op1, operand *op2)
1042 {
1043     symbol *sym1, *sym2;
1044
1045     /* if they not symbols */
1046     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1047         return FALSE;
1048
1049     sym1 = OP_SYMBOL(op1);
1050     sym2 = OP_SYMBOL(op2);
1051
1052     /* if both are itemps & one is spilt
1053        and the other is not then false */
1054     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1055         sym1->isspilt != sym2->isspilt )
1056         return FALSE ;
1057
1058     /* if they are the same */
1059     if (sym1 == sym2)
1060         return TRUE ;
1061
1062     if (sym1->rname[0] && sym2->rname[0]
1063         && strcmp (sym1->rname, sym2->rname) == 0)
1064         return TRUE;
1065
1066
1067     /* if left is a tmp & right is not */
1068     if (IS_ITEMP(op1)  && 
1069         !IS_ITEMP(op2) &&
1070         sym1->isspilt  &&
1071         (sym1->usl.spillLoc == sym2))
1072         return TRUE;
1073
1074     if (IS_ITEMP(op2)  && 
1075         !IS_ITEMP(op1) &&
1076         sym2->isspilt  &&
1077         sym1->level > 0 &&
1078         (sym2->usl.spillLoc == sym1))
1079         return TRUE ;
1080
1081     return FALSE ;
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* pic16_sameRegs - two asmops have the same registers                   */
1086 /*-----------------------------------------------------------------*/
1087 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1088 {
1089     int i;
1090
1091     if (aop1 == aop2)
1092         return TRUE ;
1093
1094     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1095                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1096
1097     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1098
1099     if (aop1->type != AOP_REG ||
1100         aop2->type != AOP_REG )
1101         return FALSE ;
1102
1103     /* This is a bit too restrictive if one is a subset of the other...
1104     if (aop1->size != aop2->size )
1105         return FALSE ;
1106     */
1107
1108     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1109 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1110
1111 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1112         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1113             return FALSE ;
1114     }
1115
1116     return TRUE ;
1117 }
1118
1119 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1120 {
1121     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1122                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1123
1124     if(aop1 == aop2)return TRUE;
1125     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1126       
1127       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1128     
1129   return TRUE;
1130 }
1131
1132
1133 /*-----------------------------------------------------------------*/
1134 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1135 /*-----------------------------------------------------------------*/
1136 void pic16_aopOp (operand *op, iCode *ic, bool result)
1137 {
1138     asmop *aop;
1139     symbol *sym;
1140     int i;
1141
1142     if (!op)
1143         return ;
1144
1145     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1146
1147     /* if this a literal */
1148     if (IS_OP_LITERAL(op)) {
1149         op->aop = aop = newAsmop(AOP_LIT);
1150         aop->aopu.aop_lit = op->operand.valOperand;
1151         aop->size = getSize(operandType(op));
1152         return;
1153     }
1154
1155     {
1156       sym_link *type = operandType(op);
1157 #if 0
1158       if(IS_PTR_CONST(type))
1159 #else
1160       if(IS_CODEPTR(type))
1161 #endif
1162         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1163     }
1164
1165     /* if already has a asmop then continue */
1166     if (op->aop)
1167         return ;
1168
1169     /* if the underlying symbol has a aop */
1170     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1171       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1172         op->aop = OP_SYMBOL(op)->aop;
1173         return;
1174     }
1175
1176     /* if this is a true symbol */
1177     if (IS_TRUE_SYMOP(op)) {    
1178         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1179       op->aop = aopForSym(ic, op, result);
1180       return ;
1181     }
1182
1183     /* this is a temporary : this has
1184     only four choices :
1185     a) register
1186     b) spillocation
1187     c) rematerialize 
1188     d) conditional   
1189     e) can be a return use only */
1190
1191     sym = OP_SYMBOL(op);
1192
1193     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1194     /* if the type is a conditional */
1195     if (sym->regType == REG_CND) {
1196         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1197         aop->size = 0;
1198         return;
1199     }
1200
1201     /* if it is spilt then two situations
1202     a) is rematerialize 
1203     b) has a spill location */
1204     if (sym->isspilt || sym->nRegs == 0) {
1205
1206 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1207       DEBUGpic16_emitcode(";","%d",__LINE__);
1208         /* rematerialize it NOW */
1209         if (sym->remat) {
1210
1211             sym->aop = op->aop = aop = aopForRemat (op);
1212 //            aop->size = getSize(sym->type);
1213 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1214             return;
1215         }
1216
1217 #if 1
1218         if (sym->accuse) {
1219             int i;
1220             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1221             aop->size = getSize(sym->type);
1222             for ( i = 0 ; i < 1 ; i++ ) {
1223                 aop->aopu.aop_str[i] = accUse[i];
1224 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1225             }
1226             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1227             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1228             return;  
1229         }
1230 #endif
1231
1232 #if 1
1233         if (sym->ruonly) {
1234           /*
1235           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1236           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1237           //pic16_allocDirReg (IC_LEFT(ic));
1238           aop->size = getSize(sym->type);
1239           */
1240
1241           unsigned i;
1242
1243           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1244           aop->size = getSize(sym->type);
1245           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1246             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1247
1248           DEBUGpic16_emitcode(";","%d",__LINE__);
1249           return;
1250         }
1251 #endif
1252         /* else spill location  */
1253         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1254             /* force a new aop if sizes differ */
1255             sym->usl.spillLoc->aop = NULL;
1256         }
1257
1258 #if 0
1259         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1260                             __FUNCTION__,__LINE__,
1261                             sym->usl.spillLoc->rname,
1262                             sym->rname, sym->usl.spillLoc->offset);
1263 #endif
1264
1265         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1266         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1267         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1268           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1269                                                   getSize(sym->type), 
1270                                                   sym->usl.spillLoc->offset, op);
1271         } else {
1272           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1273           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1274           assert (getSize(sym->type) <= 1);
1275           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1276         }
1277         aop->size = getSize(sym->type);
1278
1279         return;
1280     }
1281
1282     {
1283       sym_link *type = operandType(op);
1284 #if 0
1285       if(IS_PTR_CONST(type)) 
1286 #else
1287       if(IS_CODEPTR(type)) 
1288 #endif
1289         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1290     }
1291
1292     /* must be in a register */
1293     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1294     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1295     aop->size = sym->nRegs;
1296     for ( i = 0 ; i < sym->nRegs ;i++)
1297         aop->aopu.aop_reg[i] = sym->regs[i];
1298 }
1299
1300 /*-----------------------------------------------------------------*/
1301 /* pic16_freeAsmop - free up the asmop given to an operand               */
1302 /*----------------------------------------------------------------*/
1303 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1304 {   
1305     asmop *aop ;
1306
1307     if (!op)
1308         aop = aaop;
1309     else 
1310         aop = op->aop;
1311
1312     if (!aop)
1313         return ;
1314
1315     if (aop->freed)
1316         goto dealloc; 
1317
1318     aop->freed = 1;
1319
1320     /* depending on the asmop type only three cases need work AOP_RO
1321        , AOP_R1 && AOP_STK */
1322 #if 1
1323     switch (aop->type) {
1324         case AOP_FSR0 :
1325             if (_G.fsr0Pushed ) {
1326                 if (pop) {
1327                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1328                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1329 //                    pic16_emitcode ("pop","ar0");
1330                     _G.fsr0Pushed--;
1331                 }
1332             }
1333             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1334             break;
1335
1336         case AOP_FSR2 :
1337             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1338             break;
1339
1340         case AOP_R0 :
1341             if (_G.r0Pushed ) {
1342                 if (pop) {
1343                     pic16_emitcode ("pop","ar0");     
1344                     _G.r0Pushed--;
1345                 }
1346             }
1347             bitVectUnSetBit(ic->rUsed,R0_IDX);
1348             break;
1349
1350         case AOP_R1 :
1351             if (_G.r1Pushed ) {
1352                 if (pop) {
1353                     pic16_emitcode ("pop","ar1");
1354                     _G.r1Pushed--;
1355                 }
1356             }
1357             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1358             break;
1359
1360         case AOP_STA:
1361           {
1362             int i;
1363
1364               /* we must store the result on stack */
1365               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1366                 // operands on stack are accessible via "FSR2 + index" with index
1367                 // starting at 2 for arguments and growing from 0 downwards for
1368                 // local variables (index == 0 is not assigned so we add one here)
1369                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1370                 if (soffs <= 0) {
1371                   assert (soffs < 0);
1372                   soffs++;
1373                 } // if
1374                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1375                 for(i=0;i<aop->size;i++) {
1376                   /* initialise for stack access via frame pointer */
1377                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1378                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1379                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1380                 }
1381         
1382                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1383               }
1384
1385               if(!_G.resDirect) {
1386                 for(i=0;i<aop->size;i++) {
1387                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1388
1389                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1390                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1391                 }
1392                   
1393               }
1394               _G.resDirect = 0;
1395           }
1396           break;
1397 #if 0
1398         case AOP_STK :
1399         {
1400             int sz = aop->size;    
1401             int stk = aop->aopu.aop_stk + aop->size;
1402             bitVectUnSetBit(ic->rUsed,R0_IDX);
1403             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1404
1405             getFreePtr(ic,&aop,FALSE);
1406             
1407             if (options.stack10bit)
1408             {
1409                 /* I'm not sure what to do here yet... */
1410                 /* #STUB */
1411                 fprintf(stderr, 
1412                         "*** Warning: probably generating bad code for "
1413                         "10 bit stack mode.\n");
1414             }
1415             
1416             if (stk) {
1417                 pic16_emitcode ("mov","a,_bp");
1418                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1419                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1420             } else {
1421                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1422             }
1423
1424             while (sz--) {
1425                 pic16_emitcode("pop","acc");
1426                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1427                 if (!sz) break;
1428                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1429             }
1430             op->aop = aop;
1431             pic16_freeAsmop(op,NULL,ic,TRUE);
1432             if (_G.r0Pushed) {
1433                 pic16_emitcode("pop","ar0");
1434                 _G.r0Pushed--;
1435             }
1436
1437             if (_G.r1Pushed) {
1438                 pic16_emitcode("pop","ar1");
1439                 _G.r1Pushed--;
1440             }       
1441         }
1442 #endif
1443
1444     }
1445 #endif
1446
1447 dealloc:
1448     /* all other cases just dealloc */
1449     if (op ) {
1450         op->aop = NULL;
1451         if (IS_SYMOP(op)) {
1452             OP_SYMBOL(op)->aop = NULL;    
1453             /* if the symbol has a spill */
1454             if (SPIL_LOC(op))
1455                 SPIL_LOC(op)->aop = NULL;
1456         }
1457     }
1458 }
1459
1460 /*-----------------------------------------------------------------*/
1461 /* pic16_aopGet - for fetching value of the aop                          */
1462 /*-----------------------------------------------------------------*/
1463 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1464 {
1465     char *s = buffer ;
1466     char *rs;
1467
1468     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1469
1470     /* offset is greater than size then zero */
1471     if (offset > (aop->size - 1) &&
1472         aop->type != AOP_LIT)
1473         return zero;
1474
1475     /* depending on type */
1476     switch (aop->type) {
1477
1478     case AOP_FSR0:
1479     case AOP_FSR2:
1480       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1481       rs = Safe_calloc(1, strlen(s)+1);
1482       strcpy(rs, s);
1483       return (rs);
1484       
1485 #if 0
1486       /* if we need to increment it */
1487       while (offset > aop->coff)
1488         {
1489           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1490           aop->coff++;
1491         }
1492
1493       while (offset < aop->coff)
1494         {
1495           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1496           aop->coff--;
1497         }
1498       aop->coff = offset;
1499       if (aop->paged)
1500         {
1501           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1502           return (dname ? "acc" : "a");
1503         }
1504       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1505       rs = Safe_calloc (1, strlen (s) + 1);
1506       strcpy (rs, s);
1507       return rs;
1508 #endif
1509
1510         
1511     case AOP_IMMD:
1512         if (bit16) 
1513             sprintf (s,"%s",aop->aopu.aop_immd);
1514         else
1515             if (offset) 
1516                 sprintf(s,"(%s >> %d)",
1517                         aop->aopu.aop_immd,
1518                         offset*8);
1519             else
1520                 sprintf(s,"%s",
1521                         aop->aopu.aop_immd);
1522         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1523         rs = Safe_calloc(1,strlen(s)+1);
1524         strcpy(rs,s);   
1525         return rs;
1526         
1527     case AOP_DIR:
1528       if (offset) {
1529         sprintf(s,"(%s + %d)",
1530                 aop->aopu.aop_dir,
1531                 offset);
1532         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1533       } else
1534             sprintf(s,"%s",aop->aopu.aop_dir);
1535         rs = Safe_calloc(1,strlen(s)+1);
1536         strcpy(rs,s);   
1537         return rs;
1538         
1539     case AOP_REG:
1540       //if (dname) 
1541       //    return aop->aopu.aop_reg[offset]->dname;
1542       //else
1543             return aop->aopu.aop_reg[offset]->name;
1544         
1545     case AOP_CRY:
1546       //pic16_emitcode(";","%d",__LINE__);
1547       return aop->aopu.aop_dir;
1548         
1549     case AOP_ACC:
1550         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1551 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1552 //        assert( 0 );
1553 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1554         rs = Safe_strdup("WREG");
1555         return (rs);
1556
1557     case AOP_LIT:
1558         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1559         rs = Safe_calloc(1,strlen(s)+1);
1560         strcpy(rs,s);   
1561         return rs;
1562         
1563     case AOP_STR:
1564         aop->coff = offset ;
1565
1566 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1567 //          dname)
1568 //          return "acc";
1569         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1570           aop->type = AOP_ACC;
1571           return Safe_strdup("WREG");
1572         }
1573         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1574         
1575         return aop->aopu.aop_str[offset];
1576         
1577     case AOP_PCODE:
1578       {
1579         pCodeOp *pcop = aop->aopu.pcop;
1580         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1581         if(pcop->name) {
1582           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1583           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1584           if (offset) {
1585             sprintf(s,"(%s + %d)", pcop->name, offset);
1586           } else {
1587             sprintf(s,"%s", pcop->name);
1588           }
1589         } else
1590           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1591
1592       }
1593       rs = Safe_calloc(1,strlen(s)+1);
1594       strcpy(rs,s);   
1595       return rs;
1596
1597 #if 0
1598     case AOP_PAGED:
1599       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1600       if (offset) {
1601         sprintf(s,"(%s + %d)",
1602                 aop->aopu.aop_dir,
1603                 offset);
1604       } else
1605             sprintf(s,"%s",aop->aopu.aop_dir);
1606       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1607       rs = Safe_calloc(1,strlen(s)+1);
1608       strcpy(rs,s);   
1609       return rs;
1610 #endif
1611
1612     case AOP_STA:
1613         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1614         return (rs);
1615         
1616     case AOP_STK:
1617 //        pCodeOp *pcop = aop->aop
1618         break;
1619
1620     }
1621
1622     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1623     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1624            "aopget got unsupported aop->type");
1625     exit(0);
1626 }
1627
1628
1629
1630 /* lock has the following meaning: When allocating temporary registers
1631  * for stack variables storage, the value of the temporary register is
1632  * saved on stack. Its value is restored at the end. This procedure is
1633  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1634  * a possibility that before a call to pic16_aopOp, a temporary register
1635  * is allocated for a while and it is freed after some time, this will
1636  * mess the stack and values will not be restored properly. So use lock=1
1637  * to allocate temporary registers used internally by the programmer, and
1638  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1639  * to inform the compiler developer about a possible bug. This is an internal
1640  * feature for developing the compiler -- VR */
1641  
1642 int _TempReg_lock = 0;
1643 /*-----------------------------------------------------------------*/
1644 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1645 /*-----------------------------------------------------------------*/
1646 pCodeOp *pic16_popGetTempReg(int lock)
1647 {
1648   pCodeOp *pcop;
1649   symbol *cfunc;
1650
1651 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1652     if(_TempReg_lock) {
1653 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1654     }
1655     
1656     _TempReg_lock += lock;
1657     
1658     cfunc = currFunc;
1659     currFunc = NULL;
1660
1661     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1662     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1663       PCOR(pcop)->r->wasUsed=1;
1664       PCOR(pcop)->r->isFree=0;
1665
1666       /* push value on stack */
1667       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1668     }
1669
1670     currFunc = cfunc;
1671
1672   return pcop;
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1677 /*                           is not part of f, but don't save if   */
1678 /*                           inside v                              */
1679 /*-----------------------------------------------------------------*/
1680 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1681 {
1682   pCodeOp *pcop=NULL;
1683   symbol *cfunc;
1684   int i;
1685
1686 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1687
1688     if(_TempReg_lock) {
1689 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1690     }
1691
1692     _TempReg_lock += lock;
1693
1694     cfunc = currFunc;
1695     currFunc = NULL;
1696
1697     i = bitVectFirstBit(f);
1698     while(i < 128) {
1699
1700       /* bypass registers that are used by function */
1701       if(!bitVectBitValue(f, i)) {
1702       
1703         /* bypass registers that are already allocated for stack access */
1704         if(!bitVectBitValue(v, i))  {
1705         
1706 //          debugf("getting register rIdx = %d\n", i);
1707           /* ok, get the operand */
1708           pcop = pic16_newpCodeOpReg( i );
1709     
1710           /* should never by NULL */
1711           assert( pcop != NULL );
1712
1713           
1714           /* sanity check */
1715           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1716             int found=0;
1717             
1718               PCOR(pcop)->r->wasUsed=1;
1719               PCOR(pcop)->r->isFree=0;
1720
1721
1722               {
1723                 regs *sr;
1724               
1725                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1726
1727                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1728                       /* already used in previous steps, break */
1729                       found=1;          
1730                       break;
1731                     }
1732                   }
1733               }
1734
1735               /* caller takes care of the following */
1736 //              bitVectSetBit(v, i);
1737
1738               if(!found) {
1739                 /* push value on stack */
1740                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1742               }
1743           
1744             break;
1745           }
1746         }
1747       }
1748       i++;
1749     }
1750
1751     currFunc = cfunc;
1752
1753   return pcop;
1754 }
1755
1756
1757 /*-----------------------------------------------------------------*/
1758 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1759 /*-----------------------------------------------------------------*/
1760 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1761 {
1762   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1763
1764   _TempReg_lock -= lock;
1765
1766   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1767     PCOR(pcop)->r->isFree = 1;
1768
1769     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1770   }
1771 }
1772 /*-----------------------------------------------------------------*/
1773 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1774 /*-----------------------------------------------------------------*/
1775 pCodeOp *pic16_popGetLabel(unsigned int key)
1776 {
1777
1778   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1779
1780   if(key>max_key)
1781     max_key = key;
1782
1783   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* pic16_popCopyReg - copy a pcode operator                              */
1788 /*-----------------------------------------------------------------*/
1789 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1790 {
1791   pCodeOpReg *pcor;
1792
1793   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1794   pcor->pcop.type = pc->pcop.type;
1795   if(pc->pcop.name) {
1796     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1797       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1798   } else
1799     pcor->pcop.name = NULL;
1800
1801   pcor->r = pc->r;
1802   pcor->rIdx = pc->rIdx;
1803   pcor->r->wasUsed=1;
1804   pcor->instance = pc->instance;
1805
1806 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1807
1808   return PCOP(pcor);
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1813 /*-----------------------------------------------------------------*/
1814 pCodeOp *pic16_popGetLit(int lit)
1815 {
1816   return pic16_newpCodeOpLit(lit);
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1821 /*-----------------------------------------------------------------*/
1822 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1823 {
1824   return pic16_newpCodeOpLit2(lit, arg2);
1825 }
1826
1827
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1832 {
1833   return pic16_newpCodeOpImmd(name, offset,index, 0);
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGet - asm operator to pcode operator conversion              */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetWithString(char *str)
1841 {
1842   pCodeOp *pcop;
1843
1844
1845   if(!str) {
1846     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1847     exit (1);
1848   }
1849
1850   pcop = pic16_newpCodeOp(str,PO_STR);
1851
1852   return pcop;
1853 }
1854
1855 /*-----------------------------------------------------------------*/
1856 /* pic16_popRegFromString -                                        */
1857 /*-----------------------------------------------------------------*/
1858 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1859 {
1860
1861   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862   pcop->type = PO_DIR;
1863
1864   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1865   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1866
1867   if(!str)
1868     str = "BAD_STRING";
1869
1870   pcop->name = Safe_calloc(1,strlen(str)+1);
1871   strcpy(pcop->name,str);
1872
1873   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1874
1875   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1876
1877   /* make sure that register doesn't exist,
1878    * and operand isn't NULL
1879    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1880   if((PCOR(pcop)->r == NULL) 
1881     && (op)
1882     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1883 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1884 //              __FUNCTION__, __LINE__, str, size, offset);
1885
1886     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1887     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1888
1889   }
1890   PCOR(pcop)->instance = offset;
1891
1892   return pcop;
1893 }
1894
1895 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1896 {
1897   pCodeOp *pcop;
1898
1899 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1900
1901         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1902         PCOR(pcop)->rIdx = rIdx;
1903         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1904
1905         PCOR(pcop)->r->isFree = 0;
1906         PCOR(pcop)->r->wasUsed = 1;
1907
1908         pcop->type = PCOR(pcop)->r->pc_type;
1909
1910   return pcop;
1911 }
1912
1913 /*---------------------------------------------------------------------------------*/
1914 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1915 /*                 VR 030601                                                       */
1916 /*---------------------------------------------------------------------------------*/
1917 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1918 {
1919   pCodeOpReg2 *pcop2;
1920   pCodeOp *temp;
1921   
1922         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1923
1924         /* comment the following check, so errors to throw up */
1925 //      if(!pcop2)return NULL;
1926
1927         temp = pic16_popGet(aop_dst, offset);
1928         pcop2->pcop2 = temp;
1929         
1930   return PCOP(pcop2);
1931 }
1932
1933
1934
1935 /*--------------------------------------------------------------------------------.-*/
1936 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1937 /*                  VR 030601 , adapted by Hans Dorn                                */
1938 /*--------------------------------------------------------------------------------.-*/
1939 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1940 {
1941   pCodeOpReg2 *pcop2;
1942  
1943         pcop2 = (pCodeOpReg2 *)src;
1944         pcop2->pcop2 = dst;
1945         
1946         return PCOP(pcop2);
1947 }
1948
1949
1950
1951 /*---------------------------------------------------------------------------------*/
1952 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1953 /*                     movff instruction                                           */
1954 /*---------------------------------------------------------------------------------*/
1955 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1956 {
1957   pCodeOpReg2 *pcop2;
1958
1959         if(!noalloc) {
1960                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1961                 pcop2->pcop2 = pic16_popCopyReg(dst);
1962         } else {
1963                 /* the pCodeOp may be already allocated */
1964                 pcop2 = (pCodeOpReg2 *)(src);
1965                 pcop2->pcop2 = (pCodeOp *)(dst);
1966         }
1967
1968   return PCOP(pcop2);
1969 }
1970
1971
1972 /*-----------------------------------------------------------------*/
1973 /* pic16_popGet - asm operator to pcode operator conversion              */
1974 /*-----------------------------------------------------------------*/
1975 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1976 {
1977   //char *s = buffer ;
1978   char *rs;
1979   pCodeOp *pcop;
1980
1981     FENTRY2;
1982     /* offset is greater than
1983     size then zero */
1984
1985 //    if (offset > (aop->size - 1) &&
1986 //        aop->type != AOP_LIT)
1987 //      return NULL;  //zero;
1988
1989     /* depending on type */
1990     switch (aop->type) {
1991         
1992     case AOP_R0:
1993     case AOP_R1:
1994     case AOP_DPTR:
1995     case AOP_DPTR2:
1996         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1997         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1998         assert( 0 );
1999         return NULL;
2000
2001
2002     case AOP_FSR0:
2003     case AOP_FSR2:
2004       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2005       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2006       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2007       PCOR(pcop)->r->wasUsed = 1;
2008       PCOR(pcop)->r->isFree = 0;
2009       
2010       PCOR(pcop)->instance = offset;
2011       pcop->type = PCOR(pcop)->r->pc_type;
2012       return (pcop);
2013
2014     case AOP_IMMD:
2015       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2016       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2017
2018     case AOP_STA:
2019       /* pCodeOp is already allocated from aopForSym */
2020         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2021         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2022           
2023       return (pcop);
2024       
2025     case AOP_ACC:
2026       {
2027         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2028
2029         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2030
2031         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2032         
2033         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034         PCOR(pcop)->rIdx = rIdx;
2035         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2036         PCOR(pcop)->r->wasUsed=1;
2037         PCOR(pcop)->r->isFree=0;
2038
2039         PCOR(pcop)->instance = offset;
2040         pcop->type = PCOR(pcop)->r->pc_type;
2041 //      rs = aop->aopu.aop_reg[offset]->name;
2042 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2043         return pcop;
2044
2045
2046 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2047 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2048
2049 //      assert( 0 );
2050       }
2051         
2052     case AOP_DIR:
2053       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2054       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2055         
2056 #if 0
2057     case AOP_PAGED:
2058       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2060 #endif
2061
2062     case AOP_REG:
2063       {
2064         int rIdx;
2065         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2066         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2067
2068         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2069         
2070         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2071 //      pcop->type = PO_GPR_REGISTER;
2072         PCOR(pcop)->rIdx = rIdx;
2073         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2074         PCOR(pcop)->r->wasUsed=1;
2075         PCOR(pcop)->r->isFree=0;
2076
2077         PCOR(pcop)->instance = offset;
2078         pcop->type = PCOR(pcop)->r->pc_type;
2079         
2080         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2081         rs = aop->aopu.aop_reg[offset]->name;
2082         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2083         return pcop;
2084       }
2085
2086     case AOP_CRY:
2087         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2088
2089       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2090       PCOR(pcop)->instance = offset;
2091       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2092       //if(PCOR(pcop)->r == NULL)
2093       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2094       return pcop;
2095         
2096     case AOP_LIT:
2097         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2098       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2099
2100     case AOP_STR:
2101       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2102       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2103
2104       /*
2105       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2107       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108       pcop->type = PCOR(pcop)->r->pc_type;
2109       pcop->name = PCOR(pcop)->r->name;
2110
2111       return pcop;
2112       */
2113
2114     case AOP_PCODE:
2115       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2116                           __LINE__, 
2117                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2118       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2119       switch( aop->aopu.pcop->type ) {
2120         case PO_DIR: PCOR(pcop)->instance += offset; break;
2121         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2122         case PO_WREG:
2123             assert (offset==0);
2124             break;
2125         default:
2126           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2127           assert( 0 );  /* should never reach here */;
2128       }
2129       return pcop;
2130     }
2131
2132     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2133            "pic16_popGet got unsupported aop->type");
2134     exit(0);
2135 }
2136 /*-----------------------------------------------------------------*/
2137 /* pic16_aopPut - puts a string for a aop                                */
2138 /*-----------------------------------------------------------------*/
2139 void pic16_aopPut (asmop *aop, char *s, int offset)
2140 {
2141     char *d = buffer ;
2142     symbol *lbl ;
2143
2144     return;
2145
2146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2147
2148     if (aop->size && offset > ( aop->size - 1)) {
2149         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2150                "pic16_aopPut got offset > aop->size");
2151         exit(0);
2152     }
2153
2154     /* will assign value to value */
2155     /* depending on where it is ofcourse */
2156     switch (aop->type) {
2157     case AOP_DIR:
2158       if (offset) {
2159         sprintf(d,"(%s + %d)",
2160                 aop->aopu.aop_dir,offset);
2161         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2162
2163       } else
2164             sprintf(d,"%s",aop->aopu.aop_dir);
2165         
2166         if (strcmp(d,s)) {
2167           DEBUGpic16_emitcode(";","%d",__LINE__);
2168           if(strcmp(s,"W"))
2169             pic16_emitcode("movf","%s,w",s);
2170           pic16_emitcode("movwf","%s",d);
2171
2172           if(strcmp(s,"W")) {
2173             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2174             if(offset >= aop->size) {
2175               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2176               break;
2177             } else
2178               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2179           }
2180
2181           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2182
2183
2184         }
2185         break;
2186         
2187     case AOP_REG:
2188       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2189         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2190           /*
2191             if (*s == '@'           ||
2192                 strcmp(s,"r0") == 0 ||
2193                 strcmp(s,"r1") == 0 ||
2194                 strcmp(s,"r2") == 0 ||
2195                 strcmp(s,"r3") == 0 ||
2196                 strcmp(s,"r4") == 0 ||
2197                 strcmp(s,"r5") == 0 ||
2198                 strcmp(s,"r6") == 0 || 
2199                 strcmp(s,"r7") == 0 )
2200                 pic16_emitcode("mov","%s,%s  ; %d",
2201                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2202             else
2203           */
2204
2205           if(strcmp(s,"W")==0 )
2206             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2207
2208           pic16_emitcode("movwf","%s",
2209                    aop->aopu.aop_reg[offset]->name);
2210
2211           if(strcmp(s,zero)==0) {
2212             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2213
2214           } else if(strcmp(s,"W")==0) {
2215             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2216             pcop->type = PO_GPR_REGISTER;
2217
2218             PCOR(pcop)->rIdx = -1;
2219             PCOR(pcop)->r = NULL;
2220
2221             DEBUGpic16_emitcode(";","%d",__LINE__);
2222             pcop->name = Safe_strdup(s);
2223             pic16_emitpcode(POC_MOVFW,pcop);
2224             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2225           } else if(strcmp(s,one)==0) {
2226             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2227             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2228           } else {
2229             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230           }
2231         }
2232         break;
2233         
2234     case AOP_DPTR:
2235     case AOP_DPTR2:
2236     
2237     if (aop->type == AOP_DPTR2)
2238     {
2239         genSetDPTR(1);
2240     }
2241     
2242         if (aop->code) {
2243             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244                    "pic16_aopPut writting to code space");
2245             exit(0);
2246         }
2247         
2248         while (offset > aop->coff) {
2249             aop->coff++;
2250             pic16_emitcode ("inc","dptr");
2251         }
2252         
2253         while (offset < aop->coff) {
2254             aop->coff-- ;
2255             pic16_emitcode("lcall","__decdptr");
2256         }
2257         
2258         aop->coff = offset;
2259         
2260         /* if not in accumulater */
2261         MOVA(s);        
2262         
2263         pic16_emitcode ("movx","@dptr,a");
2264         
2265     if (aop->type == AOP_DPTR2)
2266     {
2267         genSetDPTR(0);
2268     }
2269         break;
2270         
2271     case AOP_R0:
2272     case AOP_R1:
2273         while (offset > aop->coff) {
2274             aop->coff++;
2275             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2276         }
2277         while (offset < aop->coff) {
2278             aop->coff-- ;
2279             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2280         }
2281         aop->coff = offset;
2282         
2283         if (aop->paged) {
2284             MOVA(s);           
2285             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2286             
2287         } else
2288             if (*s == '@') {
2289                 MOVA(s);
2290                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2291             } else
2292                 if (strcmp(s,"r0") == 0 ||
2293                     strcmp(s,"r1") == 0 ||
2294                     strcmp(s,"r2") == 0 ||
2295                     strcmp(s,"r3") == 0 ||
2296                     strcmp(s,"r4") == 0 ||
2297                     strcmp(s,"r5") == 0 ||
2298                     strcmp(s,"r6") == 0 || 
2299                     strcmp(s,"r7") == 0 ) {
2300                     char buffer[10];
2301                     sprintf(buffer,"a%s",s);
2302                     pic16_emitcode("mov","@%s,%s",
2303                              aop->aopu.aop_ptr->name,buffer);
2304                 } else
2305                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2306         
2307         break;
2308         
2309     case AOP_STK:
2310         if (strcmp(s,"a") == 0)
2311             pic16_emitcode("push","acc");
2312         else
2313             pic16_emitcode("push","%s",s);
2314         
2315         break;
2316         
2317     case AOP_CRY:
2318         /* if bit variable */
2319         if (!aop->aopu.aop_dir) {
2320             pic16_emitcode("clr","a");
2321             pic16_emitcode("rlc","a");
2322         } else {
2323             if (s == zero) 
2324                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2325             else
2326                 if (s == one)
2327                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2328                 else
2329                     if (!strcmp(s,"c"))
2330                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2331                     else {
2332                         lbl = newiTempLabel(NULL);
2333                         
2334                         if (strcmp(s,"a")) {
2335                             MOVA(s);
2336                         }
2337                         pic16_emitcode("clr","c");
2338                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2339                         pic16_emitcode("cpl","c");
2340                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2341                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2342                     }
2343         }
2344         break;
2345         
2346     case AOP_STR:
2347         aop->coff = offset;
2348         if (strcmp(aop->aopu.aop_str[offset],s))
2349             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2350         break;
2351         
2352     case AOP_ACC:
2353         aop->coff = offset;
2354         if (!offset && (strcmp(s,"acc") == 0))
2355             break;
2356         
2357         if (strcmp(aop->aopu.aop_str[offset],s))
2358             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2359         break;
2360
2361     default :
2362         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2363 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2364 //             "pic16_aopPut got unsupported aop->type");
2365 //      exit(0);    
2366     }    
2367
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2372 /*-----------------------------------------------------------------*/
2373 void pic16_mov2w (asmop *aop, int offset)
2374 {
2375   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2376
2377   if(is_LitAOp(aop))
2378     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2379   else
2380     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2381 }
2382
2383 static void mov2f(asmop *dst, asmop *src, int offset)
2384 {
2385   if(is_LitAOp(src)) {
2386     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2387     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2388   } else {
2389     if(pic16_sameRegsOfs(src, dst, offset))return;
2390     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2391                       pic16_popGet(dst, offset)));
2392   }
2393 }
2394
2395 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2396 {
2397   if(is_LitAOp(src)) {
2398     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2399     pic16_emitpcode(POC_MOVWF, dst);
2400   } else {
2401     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2402   }
2403 }
2404
2405 void pic16_testStackOverflow(void)
2406 {
2407 #define GSTACK_TEST_NAME        "__gstack_test"
2408
2409   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2410   
2411   {
2412     symbol *sym;
2413
2414       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2415       strcpy(sym->rname, GSTACK_TEST_NAME);
2416       checkAddSym(&externs, sym);
2417   }
2418
2419 }
2420
2421 /* push pcop into stack */
2422 void pic16_pushpCodeOp(pCodeOp *pcop)
2423 {
2424 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2425   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2426   if(pic16_options.gstack)
2427     pic16_testStackOverflow();
2428     
2429 }
2430
2431 /* pop pcop from stack */
2432 void pic16_poppCodeOp(pCodeOp *pcop)
2433 {
2434   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2435   if(pic16_options.gstack)
2436     pic16_testStackOverflow();
2437 }
2438
2439
2440 /*-----------------------------------------------------------------*/
2441 /* pushw - pushes wreg to stack                                    */
2442 /*-----------------------------------------------------------------*/
2443 void pushw(void)
2444 {
2445   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2446   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2447   if(pic16_options.gstack)
2448     pic16_testStackOverflow();
2449 }
2450
2451                 
2452 /*-----------------------------------------------------------------*/
2453 /* pushaop - pushes aop to stack                                   */
2454 /*-----------------------------------------------------------------*/
2455 void pushaop(asmop *aop, int offset)
2456 {
2457   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2458
2459   if(is_LitAOp(aop)) {
2460     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2461     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2462   } else {
2463     pic16_emitpcode(POC_MOVFF,
2464       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2465   }
2466
2467   if(pic16_options.gstack)
2468     pic16_testStackOverflow();
2469 }
2470
2471 /*-----------------------------------------------------------------*/
2472 /* popaop - pops aop from stack                                    */
2473 /*-----------------------------------------------------------------*/
2474 void popaop(asmop *aop, int offset)
2475 {
2476   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2477   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2478   if(pic16_options.gstack)
2479     pic16_testStackOverflow();
2480 }
2481
2482 void popaopidx(asmop *aop, int offset, int index)
2483 {
2484   int ofs=1;
2485
2486     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2487
2488     if(STACK_MODEL_LARGE)ofs++;
2489
2490     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2491     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2492     if(pic16_options.gstack)
2493       pic16_testStackOverflow();
2494 }
2495
2496 #if !(USE_GENERIC_SIGNED_SHIFT)
2497 /*-----------------------------------------------------------------*/
2498 /* reAdjustPreg - points a register back to where it should        */
2499 /*-----------------------------------------------------------------*/
2500 static void reAdjustPreg (asmop *aop)
2501 {
2502     int size ;
2503
2504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2505     aop->coff = 0;
2506     if ((size = aop->size) <= 1)
2507         return ;
2508     size-- ;
2509     switch (aop->type) {
2510         case AOP_R0 :
2511         case AOP_R1 :
2512             while (size--)
2513                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2514             break;          
2515         case AOP_DPTR :
2516         case AOP_DPTR2:
2517             if (aop->type == AOP_DPTR2)
2518             {
2519                 genSetDPTR(1);
2520             } 
2521             while (size--)
2522             {
2523                 pic16_emitcode("lcall","__decdptr");
2524             }
2525                 
2526             if (aop->type == AOP_DPTR2)
2527             {
2528                 genSetDPTR(0);
2529             }                
2530             break;  
2531
2532     }   
2533
2534 }
2535 #endif
2536
2537 #if 0
2538 /*-----------------------------------------------------------------*/
2539 /* opIsGptr: returns non-zero if the passed operand is             */   
2540 /* a generic pointer type.                                         */
2541 /*-----------------------------------------------------------------*/ 
2542 static int opIsGptr(operand *op)
2543 {
2544     sym_link *type = operandType(op);
2545     
2546     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2547     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2548     {
2549         return 1;
2550     }
2551     return 0;        
2552 }
2553 #endif
2554
2555 /*-----------------------------------------------------------------*/
2556 /* pic16_getDataSize - get the operand data size                         */
2557 /*-----------------------------------------------------------------*/
2558 int pic16_getDataSize(operand *op)
2559 {
2560     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2561
2562
2563     return AOP_SIZE(op);
2564
2565     // tsd- in the pic port, the genptr size is 1, so this code here
2566     // fails. ( in the 8051 port, the size was 4).
2567 #if 0
2568     int size;
2569     size = AOP_SIZE(op);
2570     if (size == GPTRSIZE)
2571     {
2572         sym_link *type = operandType(op);
2573         if (IS_GENPTR(type))
2574         {
2575             /* generic pointer; arithmetic operations
2576              * should ignore the high byte (pointer type).
2577              */
2578             size--;
2579     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2580         }
2581     }
2582     return size;
2583 #endif
2584 }
2585
2586 /*-----------------------------------------------------------------*/
2587 /* pic16_outAcc - output Acc                                             */
2588 /*-----------------------------------------------------------------*/
2589 void pic16_outAcc(operand *result)
2590 {
2591   int size,offset;
2592   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2593   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2594
2595
2596   size = pic16_getDataSize(result);
2597   if(size){
2598     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2599     size--;
2600     offset = 1;
2601     /* unsigned or positive */
2602     while(size--)
2603       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2604   }
2605
2606 }
2607
2608 /*-----------------------------------------------------------------*/
2609 /* pic16_outBitC - output a bit C                                  */
2610 /*                 Move to result the value of Carry flag -- VR    */
2611 /*-----------------------------------------------------------------*/
2612 void pic16_outBitC(operand *result)
2613 {
2614   int i;
2615
2616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2617
2618     /* if the result is bit */
2619     if (AOP_TYPE(result) == AOP_CRY) {
2620         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2621         pic16_aopPut(AOP(result),"c",0);
2622     } else {
2623
2624         i = AOP_SIZE(result);
2625         while(i--) {
2626                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2627         }
2628         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2629     }
2630 }
2631
2632 /*-----------------------------------------------------------------*/
2633 /* pic16_outBitOp - output a bit from Op                           */
2634 /*                 Move to result the value of set/clr op -- VR    */
2635 /*-----------------------------------------------------------------*/
2636 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2637 {
2638   int i;
2639
2640     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2641
2642     /* if the result is bit */
2643     if (AOP_TYPE(result) == AOP_CRY) {
2644         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2645         pic16_aopPut(AOP(result),"c",0);
2646     } else {
2647
2648         i = AOP_SIZE(result);
2649         while(i--) {
2650                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2651         }
2652         pic16_emitpcode(POC_RRCF, pcop);          
2653         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2654     }
2655 }
2656
2657 /*-----------------------------------------------------------------*/
2658 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2659 /*-----------------------------------------------------------------*/
2660 void pic16_toBoolean(operand *oper)
2661 {
2662     int size = AOP_SIZE(oper) - 1;
2663     int offset = 1;
2664
2665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2666
2667     if ( AOP_TYPE(oper) != AOP_ACC) {
2668       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2669     }
2670     while (size--) {
2671       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2672     }
2673 }
2674
2675
2676 #if !defined(GEN_Not)
2677 /*-----------------------------------------------------------------*/
2678 /* genNot - generate code for ! operation                          */
2679 /*-----------------------------------------------------------------*/
2680 static void pic16_genNot (iCode *ic)
2681 {
2682   symbol *tlbl;
2683   int size;
2684
2685   FENTRY;
2686   /* assign asmOps to operand & result */
2687   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2688   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2689
2690   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2691   /* if in bit space then a special case */
2692   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2693     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2694       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2695       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2696     } else {
2697       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2698       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2699       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2700     }
2701     goto release;
2702   }
2703
2704   size = AOP_SIZE(IC_LEFT(ic));
2705   if(size == 1) {
2706     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2707     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2708     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2709     goto release;
2710   }
2711   pic16_toBoolean(IC_LEFT(ic));
2712
2713   tlbl = newiTempLabel(NULL);
2714   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2715   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2716   pic16_outBitC(IC_RESULT(ic));
2717
2718  release:    
2719   /* release the aops */
2720   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2721   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2722 }
2723 #endif
2724
2725
2726 #if !defined(GEN_Cpl)
2727 /*-----------------------------------------------------------------*/
2728 /* genCpl - generate code for complement                           */
2729 /*-----------------------------------------------------------------*/
2730 static void pic16_genCpl (iCode *ic)
2731 {
2732   int offset = 0;
2733   int size ;
2734
2735     FENTRY;
2736     /* assign asmOps to operand & result */
2737     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2738     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2739
2740     /* if both are in bit space then 
2741     a special case */
2742     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2743         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2744
2745         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2746         pic16_emitcode("cpl","c"); 
2747         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2748         goto release; 
2749     } 
2750
2751     size = AOP_SIZE(IC_RESULT(ic));
2752     while (size--) {
2753 /*
2754         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2755         MOVA(l);       
2756         pic16_emitcode("cpl","a");
2757         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2758 */
2759         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2760               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2761         } else {
2762                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2763                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2764         }
2765         offset++;
2766
2767     }
2768
2769
2770 release:
2771     /* release the aops */
2772     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2773     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2774 }
2775 #endif
2776
2777 /*-----------------------------------------------------------------*/
2778 /* genUminusFloat - unary minus for floating points                */
2779 /*-----------------------------------------------------------------*/
2780 static void genUminusFloat(operand *op,operand *result)
2781 {
2782   int size ,offset =0 ;
2783   
2784     FENTRY;
2785     /* for this we just need to flip the 
2786     first it then copy the rest in place */
2787     size = AOP_SIZE(op);
2788
2789     while(size--) {
2790       mov2f(AOP(result), AOP(op), offset);
2791       offset++;
2792     }
2793     
2794     /* toggle the MSB's highest bit */
2795     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2796 }
2797
2798 /*-----------------------------------------------------------------*/
2799 /* genUminus - unary minus code generation                         */
2800 /*-----------------------------------------------------------------*/
2801 static void genUminus (iCode *ic)
2802 {
2803   int size, i;
2804   sym_link *optype, *rtype;
2805   symbol *label;
2806   int needLabel=0;
2807
2808     FENTRY;     
2809     
2810     /* assign asmops */
2811     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2812     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2813
2814     /* if both in bit space then special case */
2815     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2816       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2817         
2818         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2819         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2820         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2821         goto release; 
2822     } 
2823
2824     optype = operandType(IC_LEFT(ic));
2825     rtype = operandType(IC_RESULT(ic));
2826
2827     /* if float then do float stuff */
2828     if (IS_FLOAT(optype)) {
2829       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2830       goto release;
2831     }
2832
2833     /* otherwise subtract from zero by taking the 2's complement */
2834     size = AOP_SIZE(IC_LEFT(ic));
2835     label = newiTempLabel ( NULL );
2836     
2837     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2838       for (i=size-1; i > 0; i--) {
2839         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2840       } // for
2841       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2842       for (i=1; i < size; i++) {
2843         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2844         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845       } // for
2846     } else {
2847       for (i=size-1; i >= 0; i--) {
2848         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2849         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2850       } // for
2851       if (size > 1) {
2852         for (i=0; i < size-2; i++) {
2853           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2854           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2855         } // for
2856         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2857       } // if
2858       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2859     }
2860     if (needLabel)
2861       pic16_emitpLabel (label->key);
2862
2863 release:
2864     /* release the aops */
2865     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2866     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2867 }
2868
2869 #if 0
2870 /*-----------------------------------------------------------------*/
2871 /* saveRegisters - will look for a call and save the registers     */
2872 /*-----------------------------------------------------------------*/
2873 static void saveRegisters(iCode *lic) 
2874 {
2875     int i;
2876     iCode *ic;
2877     bitVect *rsave;
2878     sym_link *dtype;
2879
2880     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2881     /* look for call */
2882     for (ic = lic ; ic ; ic = ic->next) 
2883         if (ic->op == CALL || ic->op == PCALL)
2884             break;
2885
2886     if (!ic) {
2887         fprintf(stderr,"found parameter push with no function call\n");
2888         return ;
2889     }
2890
2891     /* if the registers have been saved already then
2892     do nothing */
2893     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2894         return ;
2895
2896     /* find the registers in use at this time 
2897     and push them away to safety */
2898     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2899                           ic->rUsed);
2900
2901     ic->regsSaved = 1;
2902     if (options.useXstack) {
2903         if (bitVectBitValue(rsave,R0_IDX))
2904             pic16_emitcode("mov","b,r0");
2905         pic16_emitcode("mov","r0,%s",spname);
2906         for (i = 0 ; i < pic16_nRegs ; i++) {
2907             if (bitVectBitValue(rsave,i)) {
2908                 if (i == R0_IDX)
2909                     pic16_emitcode("mov","a,b");
2910                 else
2911                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2912                 pic16_emitcode("movx","@r0,a");
2913                 pic16_emitcode("inc","r0");
2914             }
2915         }
2916         pic16_emitcode("mov","%s,r0",spname);
2917         if (bitVectBitValue(rsave,R0_IDX))
2918             pic16_emitcode("mov","r0,b");           
2919     }// else
2920     //for (i = 0 ; i < pic16_nRegs ; i++) {
2921     //    if (bitVectBitValue(rsave,i))
2922     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2923     //}
2924
2925     dtype = operandType(IC_LEFT(ic));
2926     if (currFunc && dtype && 
2927         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2928         IFFUNC_ISISR(currFunc->type) &&
2929         !ic->bankSaved) 
2930
2931         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2932
2933 }
2934 /*-----------------------------------------------------------------*/
2935 /* unsaveRegisters - pop the pushed registers                      */
2936 /*-----------------------------------------------------------------*/
2937 static void unsaveRegisters (iCode *ic)
2938 {
2939     int i;
2940     bitVect *rsave;
2941
2942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2943     /* find the registers in use at this time 
2944     and push them away to safety */
2945     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2946                           ic->rUsed);
2947     
2948     if (options.useXstack) {
2949         pic16_emitcode("mov","r0,%s",spname);   
2950         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2951             if (bitVectBitValue(rsave,i)) {
2952                 pic16_emitcode("dec","r0");
2953                 pic16_emitcode("movx","a,@r0");
2954                 if (i == R0_IDX)
2955                     pic16_emitcode("mov","b,a");
2956                 else
2957                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2958             }       
2959
2960         }
2961         pic16_emitcode("mov","%s,r0",spname);
2962         if (bitVectBitValue(rsave,R0_IDX))
2963             pic16_emitcode("mov","r0,b");
2964     } //else
2965     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2966     //    if (bitVectBitValue(rsave,i))
2967     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2968     //}
2969
2970 }  
2971 #endif
2972
2973 #if 0  // patch 14
2974 /*-----------------------------------------------------------------*/
2975 /* pushSide -                                                      */
2976 /*-----------------------------------------------------------------*/
2977 static void pushSide(operand * oper, int size)
2978 {
2979         int offset = 0;
2980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2981         while (size--) {
2982                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2983                 if (AOP_TYPE(oper) != AOP_REG &&
2984                     AOP_TYPE(oper) != AOP_DIR &&
2985                     strcmp(l,"a") ) {
2986                         pic16_emitcode("mov","a,%s",l);
2987                         pic16_emitcode("push","acc");
2988                 } else
2989                         pic16_emitcode("push","%s",l);
2990         }
2991 }
2992 #endif // patch 14
2993
2994 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2995 {
2996   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2997     pic16_emitpcode(POC_MOVFW, src);
2998     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2999   } else {
3000     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3001         src, pic16_popGet(AOP(op), offset)));
3002   }
3003 }
3004
3005
3006 /*-----------------------------------------------------------------*/
3007 /* assignResultValue - assign results to oper, rescall==1 is       */
3008 /*                     called from genCall() or genPcall()         */
3009 /*-----------------------------------------------------------------*/
3010 static void assignResultValue(operand * oper, int rescall)
3011 {
3012   int size = AOP_SIZE(oper);
3013   int offset=0;
3014   
3015     FENTRY2;
3016 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3017     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3018
3019     if(rescall) {
3020       /* assign result from a call/pcall function() */
3021                 
3022       /* function results are stored in a special order,
3023        * see top of file with Function return policy, or manual */
3024
3025       if(size <= 4) {
3026         /* 8-bits, result in WREG */
3027         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3028                         
3029         if(size>1) {
3030           /* 16-bits, result in PRODL:WREG */
3031           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3032         }
3033                         
3034         if(size>2) {
3035           /* 24-bits, result in PRODH:PRODL:WREG */
3036           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3037         }
3038                         
3039         if(size>3) {
3040           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3041           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3042         }
3043       
3044       } else {
3045         /* >32-bits, result on stack, and FSR0 points to beginning.
3046          * Fix stack when done */
3047         /* FIXME FIXME */
3048 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3049         while (size--) {
3050 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3051 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3052                 
3053           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3054           GpsuedoStkPtr++;
3055         }
3056                         
3057         /* fix stack */
3058         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3059         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3060         if(STACK_MODEL_LARGE) {
3061           emitSKPNC;
3062           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3063         }
3064       }                 
3065     } else {
3066       int areg = 0;             /* matching argument register */
3067       
3068 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3069       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3070
3071
3072       /* its called from genReceive (probably) -- VR */
3073       /* I hope this code will not be called from somewhere else in the future! 
3074        * We manually set the pseudo stack pointer in genReceive. - dw
3075        */
3076       if(!GpsuedoStkPtr && _G.useWreg) {
3077 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3078
3079         /* The last byte in the assignment is in W */
3080         if(areg <= GpsuedoStkPtr) {
3081           size--;
3082           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3083           offset++;
3084 //          debugf("receive from WREG\n", 0);
3085         }
3086         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3087       }
3088 //      GpsuedoStkPtr++;
3089       _G.stack_lat = AOP_SIZE(oper)-1;
3090
3091       while (size) {
3092         size--;
3093         GpsuedoStkPtr++;
3094         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3095 //        debugf("receive from STACK\n", 0);
3096         offset++;
3097       }
3098     }
3099 }
3100
3101
3102 /*-----------------------------------------------------------------*/
3103 /* genIpush - generate code for pushing this gets a little complex */
3104 /*-----------------------------------------------------------------*/
3105 static void genIpush (iCode *ic)
3106 {
3107 //  int size, offset=0;
3108
3109   FENTRY;
3110   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3111
3112   if(ic->parmPush) {
3113     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3114
3115     /* send to stack as normal */
3116     addSet(&_G.sendSet,ic);
3117 //    addSetHead(&_G.sendSet,ic);
3118     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3119   }
3120
3121         
3122 #if 0
3123     int size, offset = 0 ;
3124     char *l;
3125
3126
3127     /* if this is not a parm push : ie. it is spill push 
3128     and spill push is always done on the local stack */
3129     if (!ic->parmPush) {
3130
3131         /* and the item is spilt then do nothing */
3132         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3133             return ;
3134
3135         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3136         size = AOP_SIZE(IC_LEFT(ic));
3137         /* push it on the stack */
3138         while(size--) {
3139             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3140             if (*l == '#') {
3141                 MOVA(l);
3142                 l = "acc";
3143             }
3144             pic16_emitcode("push","%s",l);
3145         }
3146         return ;        
3147     }
3148
3149     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3150 #endif
3151 }
3152
3153 /*-----------------------------------------------------------------*/
3154 /* genIpop - recover the registers: can happen only for spilling   */
3155 /*-----------------------------------------------------------------*/
3156 static void genIpop (iCode *ic)
3157 {
3158   FENTRY;
3159   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3160 #if 0
3161     int size,offset ;
3162
3163
3164     /* if the temp was not pushed then */
3165     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3166         return ;
3167
3168     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3169     size = AOP_SIZE(IC_LEFT(ic));
3170     offset = (size-1);
3171     while (size--) 
3172         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3173                                    FALSE,TRUE));
3174
3175     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3176 #endif
3177 }
3178
3179 #if 0
3180 /*-----------------------------------------------------------------*/
3181 /* unsaverbank - restores the resgister bank from stack            */
3182 /*-----------------------------------------------------------------*/
3183 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3184 {
3185   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3186 #if 0
3187     int i;
3188     asmop *aop ;
3189     regs *r = NULL;
3190
3191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3192     if (popPsw) {
3193         if (options.useXstack) {
3194             aop = newAsmop(0);
3195             r = getFreePtr(ic,&aop,FALSE);
3196             
3197             
3198             pic16_emitcode("mov","%s,_spx",r->name);
3199             pic16_emitcode("movx","a,@%s",r->name);
3200             pic16_emitcode("mov","psw,a");
3201             pic16_emitcode("dec","%s",r->name);
3202             
3203         }else
3204             pic16_emitcode ("pop","psw");
3205     }
3206
3207     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3208         if (options.useXstack) {       
3209             pic16_emitcode("movx","a,@%s",r->name);
3210             //pic16_emitcode("mov","(%s+%d),a",
3211             //       regspic16[i].base,8*bank+regspic16[i].offset);
3212             pic16_emitcode("dec","%s",r->name);
3213
3214         } else 
3215           pic16_emitcode("pop",""); //"(%s+%d)",
3216         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3217     }
3218
3219     if (options.useXstack) {
3220
3221         pic16_emitcode("mov","_spx,%s",r->name);
3222         pic16_freeAsmop(NULL,aop,ic,TRUE);
3223
3224     }
3225 #endif 
3226 }
3227
3228 /*-----------------------------------------------------------------*/
3229 /* saverbank - saves an entire register bank on the stack          */
3230 /*-----------------------------------------------------------------*/
3231 static void saverbank (int bank, iCode *ic, bool pushPsw)
3232 {
3233   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3234 #if 0
3235     int i;
3236     asmop *aop ;
3237     regs *r = NULL;
3238
3239     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3240     if (options.useXstack) {
3241
3242         aop = newAsmop(0);
3243         r = getFreePtr(ic,&aop,FALSE);  
3244         pic16_emitcode("mov","%s,_spx",r->name);
3245
3246     }
3247
3248     for (i = 0 ; i < pic16_nRegs ;i++) {
3249         if (options.useXstack) {
3250             pic16_emitcode("inc","%s",r->name);
3251             //pic16_emitcode("mov","a,(%s+%d)",
3252             //         regspic16[i].base,8*bank+regspic16[i].offset);
3253             pic16_emitcode("movx","@%s,a",r->name);           
3254         } else 
3255           pic16_emitcode("push","");// "(%s+%d)",
3256                      //regspic16[i].base,8*bank+regspic16[i].offset);
3257     }
3258     
3259     if (pushPsw) {
3260         if (options.useXstack) {
3261             pic16_emitcode("mov","a,psw");
3262             pic16_emitcode("movx","@%s,a",r->name);     
3263             pic16_emitcode("inc","%s",r->name);
3264             pic16_emitcode("mov","_spx,%s",r->name);       
3265             pic16_freeAsmop (NULL,aop,ic,TRUE);
3266             
3267         } else
3268             pic16_emitcode("push","psw");
3269         
3270         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3271     }
3272     ic->bankSaved = 1;
3273 #endif
3274 }
3275 #endif  /* 0 */
3276
3277
3278 static int wparamCmp(void *p1, void *p2)
3279 {
3280   return (!strcmp((char *)p1, (char *)p2));
3281 }
3282
3283 int inWparamList(char *s)
3284 {
3285   return isinSetWith(wparamList, s, wparamCmp);
3286
3287
3288
3289 /*-----------------------------------------------------------------*/
3290 /* genCall - generates a call statement                            */
3291 /*-----------------------------------------------------------------*/
3292 static void genCall (iCode *ic)
3293 {
3294   sym_link *ftype;   
3295   int stackParms=0;
3296   int use_wreg=0;
3297   int inwparam=0;
3298   char *fname;
3299   
3300     FENTRY;
3301
3302     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3303     /* if caller saves & we have not saved then */
3304 //    if (!ic->regsSaved)
3305 //      saveRegisters(ic);
3306
3307         /* initialise stackParms for IPUSH pushes */
3308 //      stackParms = psuedoStkPtr;
3309 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3310     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3311     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3312
3313 #if 0
3314     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3315 #endif
3316
3317     /* if send set is not empty the assign */
3318     if (_G.sendSet) {
3319       iCode *sic;
3320       int psuedoStkPtr=-1; 
3321       int firstTimeThruLoop = 1;
3322
3323
3324         /* reverse sendSet if function is not reentrant */
3325         if(!IFFUNC_ISREENT(ftype))
3326           _G.sendSet = reverseSet(_G.sendSet);
3327
3328         /* First figure how many parameters are getting passed */
3329         stackParms = 0;
3330         use_wreg = 0;
3331         
3332         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3333           int size;
3334 //          int offset = 0;
3335
3336             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3337             size = AOP_SIZE(IC_LEFT(sic));
3338
3339             stackParms += size;
3340
3341             /* pass the last byte through WREG */
3342             if(inwparam) {
3343
3344               while (size--) {
3345                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3348
3349                 if(!firstTimeThruLoop) {
3350                   /* If this is not the first time we've been through the loop
3351                    * then we need to save the parameter in a temporary
3352                    * register. The last byte of the last parameter is
3353                    * passed in W. */
3354
3355                   pushw();
3356 //                  --psuedoStkPtr;             // sanity check
3357                   use_wreg = 1;
3358                 }
3359                 
3360                 firstTimeThruLoop=0;
3361
3362                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3363
3364 //                offset++;
3365               }
3366             } else {
3367               /* all arguments are passed via stack */
3368               use_wreg = 0;
3369
3370               while (size--) {
3371                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3372                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3373                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3374
3375 //                pushaop(AOP(IC_LEFT(sic)), size);
3376                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3377
3378                 if(!_G.resDirect)
3379                   pushw();
3380               }
3381             }
3382
3383             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3384           }
3385
3386           if(inwparam) {
3387             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3388               pushw();  /* save last parameter to stack if functions has varargs */
3389               use_wreg = 0;
3390             } else
3391               use_wreg = 1;
3392           } else use_wreg = 0;
3393
3394           _G.stackRegSet = _G.sendSet;
3395           _G.sendSet = NULL;
3396     }
3397
3398     /* make the call */
3399     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3400
3401     GpsuedoStkPtr=0;
3402     
3403     /* if we need to assign a result value */
3404     if ((IS_ITEMP(IC_RESULT(ic))
3405           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3406               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3407         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3408
3409       _G.accInUse++;
3410       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3411       _G.accInUse--;
3412
3413       assignResultValue(IC_RESULT(ic), 1);
3414
3415       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3416                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3417                 
3418       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3419     }
3420
3421     if(!stackParms && ic->parmBytes) {
3422       stackParms = ic->parmBytes;
3423     }
3424       
3425     stackParms -= use_wreg;
3426     
3427     if(stackParms>0) {
3428       if(stackParms == 1) {
3429         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3430       } else {
3431         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3432         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3433       }
3434       if(STACK_MODEL_LARGE) {
3435         emitSKPNC;
3436         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3437       }
3438     }
3439
3440 #if 0
3441     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3442 #endif
3443
3444     /* adjust the stack for parameters if required */
3445 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3446
3447 #if 0
3448       /* if register bank was saved then pop them */
3449       if (ic->bankSaved)
3450         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3451
3452       /* if we hade saved some registers then unsave them */
3453       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3454         unsaveRegisters (ic);
3455 #endif
3456 }
3457
3458
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genPcall - generates a call by pointer statement                */
3462 /*            new version, created from genCall - HJD              */
3463 /*-----------------------------------------------------------------*/
3464 static void genPcall (iCode *ic)
3465 {
3466   sym_link *ftype, *fntype;
3467   int stackParms=0;
3468   symbol *retlbl = newiTempLabel(NULL);
3469   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3470   
3471     FENTRY;
3472
3473     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3474     fntype = operandType( IC_LEFT(ic) )->next;
3475
3476     /* if send set is not empty the assign */
3477     if (_G.sendSet) {
3478       iCode *sic;
3479       int psuedoStkPtr=-1; 
3480
3481       /* reverse sendSet if function is not reentrant */
3482       if(!IFFUNC_ISREENT(fntype))
3483         _G.sendSet = reverseSet(_G.sendSet);
3484
3485       stackParms = 0;
3486       
3487       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3488         int size;
3489
3490           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3491           size = AOP_SIZE(IC_LEFT(sic));
3492           stackParms += size;
3493
3494           /* all parameters are passed via stack, since WREG is clobbered
3495            * by the calling sequence */
3496           while (size--) {
3497             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3499             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3500
3501             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3502             pushw();
3503           }
3504
3505           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3506       }
3507
3508       _G.stackRegSet = _G.sendSet;
3509       _G.sendSet = NULL;
3510     }
3511
3512     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3513
3514     // push return address
3515     // push $ on return stack, then replace with retlbl
3516
3517     /* Thanks to Thorsten Klose for pointing out that the following
3518      * snippet should be interrupt safe */
3519     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3520     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3521
3522     pic16_emitpcodeNULLop(POC_PUSH);
3523
3524     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3525     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3526     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3527     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3528     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3530
3531
3532     /* restore interrupt control register */
3533     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3534     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3535
3536     /* make the call by writing the pointer into pc */
3537     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3538     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3539
3540     // note: MOVFF to PCL not allowed
3541     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3542     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3543
3544
3545     /* return address is here: (X) */
3546     pic16_emitpLabelFORCE(retlbl->key);
3547
3548     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3549
3550     GpsuedoStkPtr=0;
3551     /* if we need assign a result value */
3552     if ((IS_ITEMP(IC_RESULT(ic))
3553           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3554               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3555         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3556
3557       _G.accInUse++;
3558       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3559       _G.accInUse--;
3560
3561       assignResultValue(IC_RESULT(ic), 1);
3562
3563       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3564               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3565                 
3566       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3567     }
3568
3569 //    stackParms -= use_wreg;
3570     
3571     if(stackParms>0) {
3572       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3573       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3574       if(STACK_MODEL_LARGE) {
3575         emitSKPNC;
3576         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3577       }
3578     }
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* resultRemat - result  is rematerializable                       */
3583 /*-----------------------------------------------------------------*/
3584 static int resultRemat (iCode *ic)
3585 {
3586   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3587   if (SKIP_IC(ic) || ic->op == IFX)
3588     return 0;
3589
3590   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3591     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3592     if (sym->remat && !POINTER_SET(ic)) 
3593       return 1;
3594   }
3595
3596   return 0;
3597 }
3598
3599 #if defined(__BORLANDC__) || defined(_MSC_VER)
3600 #define STRCASECMP stricmp
3601 #else
3602 #define STRCASECMP strcasecmp
3603 #endif
3604
3605 #if 0
3606 /*-----------------------------------------------------------------*/
3607 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3608 /*-----------------------------------------------------------------*/
3609 static bool inExcludeList(char *s)
3610 {
3611   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3612     int i =0;
3613     
3614     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3615     if (options.excludeRegs[i] &&
3616     STRCASECMP(options.excludeRegs[i],"none") == 0)
3617         return FALSE ;
3618
3619     for ( i = 0 ; options.excludeRegs[i]; i++) {
3620         if (options.excludeRegs[i] &&
3621         STRCASECMP(s,options.excludeRegs[i]) == 0)
3622             return TRUE;
3623     }
3624     return FALSE ;
3625 }
3626 #endif
3627
3628 /*-----------------------------------------------------------------*/
3629 /* genFunction - generated code for function entry                 */
3630 /*-----------------------------------------------------------------*/
3631 static void genFunction (iCode *ic)
3632 {
3633   symbol *sym;
3634   sym_link *ftype;
3635   
3636     FENTRY;
3637     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3638
3639     pic16_labelOffset += (max_key+4);
3640     max_key=0;
3641     GpsuedoStkPtr=0;
3642     _G.nRegsSaved = 0;
3643         
3644     ftype = operandType(IC_LEFT(ic));
3645     sym = OP_SYMBOL(IC_LEFT(ic));
3646
3647     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3648       /* create an absolute section at the interrupt vector:
3649        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3650       symbol *asym;
3651       char asymname[128];
3652       pBlock *apb;
3653
3654 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3655
3656         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3657           sprintf(asymname, "ivec_%s", sym->name);
3658         else
3659           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3660         asym = newSymbol(asymname, 0);
3661
3662         /* FIXME: when an interrupt is declared as naked, do not emit the special
3663          * wrapper segment at vector address. The user should take care for this
3664          * instead. -- VR */
3665         
3666         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3667         pic16_addpBlock( apb );
3668
3669         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3670         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3671         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3672                 
3673         /* mark the end of this tiny function */
3674         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3675
3676         {
3677           absSym *abSym;
3678
3679             abSym = Safe_calloc(1, sizeof(absSym));
3680             strcpy(abSym->name, asymname);
3681
3682             switch( FUNC_INTNO(sym->type) ) {
3683               case 0: abSym->address = 0x000000; break;
3684               case 1: abSym->address = 0x000008; break;
3685               case 2: abSym->address = 0x000018; break;
3686               
3687               default:
3688                 fprintf(stderr, "no interrupt number is given\n");
3689                 abSym->address = -1; break;
3690             }
3691
3692             /* relocate interrupt vectors if needed */
3693             if(abSym->address != -1)
3694               abSym->address += pic16_options.ivt_loc;
3695
3696             addSet(&absSymSet, abSym);
3697         }
3698     }
3699
3700     /* create the function header */
3701     pic16_emitcode(";","-----------------------------------------");
3702     pic16_emitcode(";"," function %s",sym->name);
3703     pic16_emitcode(";","-----------------------------------------");
3704
3705     pic16_emitcode("","%s:",sym->rname);
3706     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3707
3708
3709     {
3710       absSym *ab;
3711
3712         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3713           if(!strcmp(ab->name, sym->rname)) {
3714             pic16_pBlockConvert2Absolute(pb);
3715             break;
3716           }
3717         }
3718     }
3719
3720
3721     if(IFFUNC_ISNAKED(ftype)) {
3722       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3723       return;
3724     }
3725         
3726     /* if critical function then turn interrupts off */
3727     if (IFFUNC_ISCRITICAL(ftype)) {
3728       //pic16_emitcode("clr","ea");
3729     }
3730
3731     currFunc = sym;             /* update the currFunc symbol */
3732     _G.fregsUsed = sym->regsUsed;
3733     _G.sregsAlloc = newBitVect(128);
3734     
3735
3736     /* if this is an interrupt service routine then
3737      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3738     if (IFFUNC_ISISR(sym->type)) {
3739         _G.usefastretfie = 1;   /* use shadow registers by default */
3740         
3741         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3742         if(!FUNC_ISSHADOWREGS(sym->type)) {
3743           /* do not save WREG,STATUS,BSR for high priority interrupts
3744            * because they are stored in the hardware shadow registers already */
3745           _G.usefastretfie = 0;
3746           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3747           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3748           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3749         }
3750
3751         /* these should really be optimized somehow, because not all
3752          * interrupt handlers modify them */
3753         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3754         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3755         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3756         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3757         
3758 //        pic16_pBlockConvert2ISR(pb);
3759     }
3760
3761     /* emit code to setup stack frame if user enabled,
3762      * and function is not main() */
3763     
3764 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3765     if(strcmp(sym->name, "main")) {
3766       if(0 
3767         || !options.ommitFramePtr 
3768 //        || sym->regsUsed
3769         || IFFUNC_ARGS(sym->type)
3770         || FUNC_HASSTACKPARM(sym->etype)
3771         ) {
3772         /* setup the stack frame */
3773         if(STACK_MODEL_LARGE)
3774           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3775         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3776
3777         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3778         if(STACK_MODEL_LARGE)
3779           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3780       }
3781     }
3782
3783     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3784           && sym->stack) {
3785
3786       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3787
3788       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3789       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3790       emitSKPC;
3791       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3792     }
3793           
3794     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3795       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3796         _G.useWreg = 0;
3797       else
3798         _G.useWreg = 1;
3799     } else
3800       _G.useWreg = 0;
3801
3802     /* if callee-save to be used for this function
3803      * then save the registers being used in this function */
3804 //    if (IFFUNC_CALLEESAVES(sym->type))
3805     {
3806       int i;
3807
3808         /* if any registers used */
3809         if (sym->regsUsed) {
3810           /* save the registers used */
3811           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3812           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3813           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3814             if (bitVectBitValue(sym->regsUsed,i)) {
3815               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3816               _G.nRegsSaved++;
3817
3818               if(!pic16_regWithIdx(i)->wasUsed) {
3819                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3820                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3821                 pic16_regWithIdx(i)->wasUsed = 1;
3822               }
3823             }
3824           }
3825           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3826         }
3827     }
3828         
3829     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3830 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3831 }
3832
3833 /*-----------------------------------------------------------------*/
3834 /* genEndFunction - generates epilogue for functions               */
3835 /*-----------------------------------------------------------------*/
3836 static void genEndFunction (iCode *ic)
3837 {
3838   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3839
3840     FENTRY;
3841
3842     if(IFFUNC_ISNAKED(sym->type)) {
3843       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3844       return;
3845     }
3846
3847     _G.stack_lat = 0;
3848
3849     /* add code for ISCRITICAL */
3850     if(IFFUNC_ISCRITICAL(sym->type)) {
3851       /* if critical function, turn on interrupts */
3852       
3853       /* TODO: add code here -- VR */
3854     }
3855     
3856 //    sym->regsUsed = _G.fregsUsed;
3857     
3858     /* now we need to restore the registers */
3859     /* if any registers used */
3860
3861     /* first restore registers that might be used for stack access */
3862     if(_G.sregsAllocSet) {
3863     regs *sr;
3864     
3865       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3866       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3867         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3868       }
3869     }
3870
3871     if (sym->regsUsed) {
3872       int i;
3873
3874         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3875         /* restore registers used */
3876         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3877         for ( i = sym->regsUsed->size; i >= 0; i--) {
3878           if (bitVectBitValue(sym->regsUsed,i)) {
3879             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3880             _G.nRegsSaved--;
3881           }
3882         }
3883         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3884     }
3885
3886       
3887
3888     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3889           && sym->stack) {
3890       if (sym->stack == 1) {
3891         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3892         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3893       } else {
3894         // we have to add more than one...
3895         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3896         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3897         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3898         emitSKPNC;
3899         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3900         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3901         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3902       }
3903     }
3904
3905     if(strcmp(sym->name, "main")) {
3906       if(0
3907         || !options.ommitFramePtr
3908 //        || sym->regsUsed
3909         || IFFUNC_ARGS(sym->type)
3910         || FUNC_HASSTACKPARM(sym->etype)
3911         ) {
3912         /* restore stack frame */
3913         if(STACK_MODEL_LARGE)
3914           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3915         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3916       }
3917     }
3918
3919     _G.useWreg = 0;
3920
3921     if (IFFUNC_ISISR(sym->type)) {
3922       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3923       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3924       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3925       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3926
3927       if(!FUNC_ISSHADOWREGS(sym->type)) {
3928         /* do not restore interrupt vector for WREG,STATUS,BSR
3929          * for high priority interrupt, see genFunction */
3930         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3931         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3932         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3933       }
3934 //      _G.interruptvector = 0;         /* sanity check */
3935
3936
3937       /* if debug then send end of function */
3938 /*      if (options.debug && currFunc)  */
3939       if (currFunc) {
3940         debugFile->writeEndFunction (currFunc, ic, 1);
3941       }
3942         
3943       if(_G.usefastretfie)
3944         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3945       else
3946         pic16_emitpcodeNULLop(POC_RETFIE);
3947
3948       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3949       
3950       _G.usefastretfie = 0;
3951       return;
3952     }
3953
3954     if (IFFUNC_ISCRITICAL(sym->type)) {
3955       pic16_emitcode("setb","ea");
3956     }
3957
3958     /* if debug then send end of function */
3959     if (currFunc) {
3960       debugFile->writeEndFunction (currFunc, ic, 1);
3961     }
3962
3963     /* insert code to restore stack frame, if user enabled it
3964      * and function is not main() */
3965          
3966
3967     pic16_emitpcodeNULLop(POC_RETURN);
3968
3969     /* Mark the end of a function */
3970     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3971 }
3972
3973
3974 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3975 {
3976   unsigned long lit=1;
3977   operand *op;
3978
3979     op = IC_LEFT(ic);
3980   
3981     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3982     if(AOP_TYPE(op) == AOP_LIT) {
3983       if(!IS_FLOAT(operandType( op ))) {
3984         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3985       } else {
3986         union {
3987           unsigned long lit_int;
3988           float lit_float;
3989         } info;
3990         
3991         /* take care if literal is a float */
3992         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3993         lit = info.lit_int;
3994       }
3995     }
3996
3997     if(is_LitOp(op)) {
3998       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3999         pic16_emitpcode(POC_CLRF, dest);
4000       } else {
4001         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4002         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4003       }
4004     } else {
4005       if(dest->type == PO_WREG && (offset == 0)) {
4006         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4007       return;
4008     }
4009     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4010   }
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genRet - generate code for return statement                     */
4015 /*-----------------------------------------------------------------*/
4016 static void genRet (iCode *ic)
4017 {
4018   int size;
4019   operand *left;
4020
4021     FENTRY;
4022         /* if we have no return value then
4023          * just generate the "ret" */
4024         
4025         if (!IC_LEFT(ic)) 
4026                 goto jumpret;       
4027     
4028         /* we have something to return then
4029          * move the return value into place */
4030         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4031         size = AOP_SIZE(IC_LEFT(ic));
4032
4033         if(size <= 4) {
4034           if(size>3)
4035             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4036           
4037           if(size>2)
4038             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4039
4040           if(size>1)
4041             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4042           
4043           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4044
4045         } else {
4046                 /* >32-bits, setup stack and FSR0 */
4047                 while (size--) {
4048 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4049 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4050
4051                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4052
4053 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4054                         GpsuedoStkPtr++;
4055                 }
4056                         
4057                 /* setup FSR0 */
4058                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4059                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4060
4061                 if(STACK_MODEL_LARGE) {
4062                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4063                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4064                 } else {
4065                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4066                 }
4067         }
4068                                 
4069 #if 0
4070         /* old code, left here for reference -- VR */    
4071         while (size--) {
4072           char *l ;
4073
4074                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4075                         /* #NOCHANGE */
4076                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4077                         pic16_emitpcomment("push %s",l);
4078                         pushed++;
4079                 } else {
4080                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4081                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4082                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4083                         
4084                         if (strcmp(fReturn[offset],l)) {
4085                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4086                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4087                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4088                                 } else {
4089                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4090                                 }
4091                                 
4092                                 if(size) {
4093                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4094                                 }
4095                                 offset++;
4096                         }
4097                 }
4098         }    
4099
4100         if (pushed) {
4101                 while(pushed) {
4102                         pushed--;
4103                         if (strcmp(fReturn[pushed],"a"))
4104                                 pic16_emitcode("pop",fReturn[pushed]);
4105                         else
4106                                 pic16_emitcode("pop","acc");
4107                 }
4108         }
4109 #endif
4110
4111
4112         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4113     
4114 jumpret:
4115         /* generate a jump to the return label
4116          * if the next is not the return statement */
4117         if (!(ic->next && ic->next->op == LABEL
4118                 && IC_LABEL(ic->next) == returnLabel)) {
4119         
4120                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4121                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4122         }
4123 }
4124
4125 /*-----------------------------------------------------------------*/
4126 /* genLabel - generates a label                                    */
4127 /*-----------------------------------------------------------------*/
4128 static void genLabel (iCode *ic)
4129 {
4130   FENTRY;
4131
4132   /* special case never generate */
4133   if (IC_LABEL(ic) == entryLabel)
4134     return ;
4135
4136   pic16_emitpLabel(IC_LABEL(ic)->key);
4137 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genGoto - generates a goto                                      */
4142 /*-----------------------------------------------------------------*/
4143 //tsd
4144 static void genGoto (iCode *ic)
4145 {
4146   FENTRY;
4147   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4148 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4149 }
4150
4151
4152 /*-----------------------------------------------------------------*/
4153 /* genMultbits :- multiplication of bits                           */
4154 /*-----------------------------------------------------------------*/
4155 static void genMultbits (operand *left, 
4156                          operand *right, 
4157                          operand *result)
4158 {
4159   FENTRY;
4160
4161   if(!pic16_sameRegs(AOP(result),AOP(right)))
4162     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4163
4164   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4165   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4166   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4167
4168 }
4169
4170
4171 /*-----------------------------------------------------------------*/
4172 /* genMultOneByte : 8 bit multiplication & division                */
4173 /*-----------------------------------------------------------------*/
4174 static void genMultOneByte (operand *left,
4175                             operand *right,
4176                             operand *result)
4177 {
4178
4179   FENTRY;
4180   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4181   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4182
4183   /* (if two literals, the value is computed before) */
4184   /* if one literal, literal on the right */
4185   if (AOP_TYPE(left) == AOP_LIT){
4186     operand *t = right;
4187     right = left;
4188     left = t;
4189   }
4190
4191         /* size is already checked in genMult == 1 */
4192 //      size = AOP_SIZE(result);
4193
4194         if (AOP_TYPE(right) == AOP_LIT){
4195                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4196                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4197                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4198                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4199         } else {
4200                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4201                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4202                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4203                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4204         }
4205         
4206         pic16_genMult8X8_8 (left, right,result);
4207 }
4208
4209 /*-----------------------------------------------------------------*/
4210 /* genMultOneWord : 16 bit multiplication                          */
4211 /*-----------------------------------------------------------------*/
4212 static void genMultOneWord (operand *left,
4213                             operand *right,
4214                             operand *result)
4215 {
4216   FENTRY;
4217   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4218   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4219
4220   /* (if two literals, the value is computed before)
4221    * if one literal, literal on the right */
4222   if (AOP_TYPE(left) == AOP_LIT){
4223     operand *t = right;
4224     right = left;
4225     left = t;
4226   }
4227
4228   /* size is checked already == 2 */
4229 //  size = AOP_SIZE(result);
4230
4231   if (AOP_TYPE(right) == AOP_LIT) {
4232     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4233       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4234       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4235       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4236   } else {
4237     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4238       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4239       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4240       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4241   }
4242         
4243   pic16_genMult16X16_16(left, right,result);
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* genMultOneLong : 32 bit multiplication                          */
4248 /*-----------------------------------------------------------------*/
4249 static void genMultOneLong (operand *left,
4250                             operand *right,
4251                             operand *result)
4252 {
4253   FENTRY;
4254   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4255   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4256
4257   /* (if two literals, the value is computed before)
4258    * if one literal, literal on the right */
4259   if (AOP_TYPE(left) == AOP_LIT){
4260     operand *t = right;
4261     right = left;
4262     left = t;
4263   }
4264
4265   /* size is checked already == 4 */
4266 //  size = AOP_SIZE(result);
4267
4268   if (AOP_TYPE(right) == AOP_LIT) {
4269     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4270         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4271         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4272         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4273   } else {
4274     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4275         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4276         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4277         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4278   }
4279         
4280   pic16_genMult32X32_32(left, right,result);
4281 }
4282
4283
4284
4285 /*-----------------------------------------------------------------*/
4286 /* genMult - generates code for multiplication                     */
4287 /*-----------------------------------------------------------------*/
4288 static void genMult (iCode *ic)
4289 {
4290   operand *left = IC_LEFT(ic);
4291   operand *right = IC_RIGHT(ic);
4292   operand *result= IC_RESULT(ic);   
4293
4294     FENTRY;
4295         /* assign the amsops */
4296         pic16_aopOp (left,ic,FALSE);
4297         pic16_aopOp (right,ic,FALSE);
4298         pic16_aopOp (result,ic,TRUE);
4299
4300         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4301
4302         /* special cases first *
4303         * both are bits */
4304         if (AOP_TYPE(left) == AOP_CRY
4305                 && AOP_TYPE(right)== AOP_CRY) {
4306                 genMultbits(left,right,result);
4307           goto release ;
4308         }
4309
4310         /* if both are of size == 1 */
4311         if(AOP_SIZE(left) == 1
4312                 && AOP_SIZE(right) == 1) {
4313                 genMultOneByte(left,right,result);
4314           goto release ;
4315         }
4316
4317         /* if both are of size == 2 */
4318         if(AOP_SIZE(left) == 2
4319                 && AOP_SIZE(right) == 2) {
4320                 genMultOneWord(left, right, result);
4321           goto release;
4322         }
4323         
4324         /* if both are of size == 4 */
4325         if(AOP_SIZE(left) == 4
4326                 && AOP_SIZE(right) == 4) {
4327                 genMultOneLong(left, right, result);
4328           goto release;
4329         }
4330         
4331         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4332
4333
4334         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4335         /* should have been converted to function call */
4336         assert(0) ;
4337
4338 release :
4339         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4341         pic16_freeAsmop(result,NULL,ic,TRUE); 
4342 }
4343
4344 /*-----------------------------------------------------------------*/
4345 /* genDivbits :- division of bits                                  */
4346 /*-----------------------------------------------------------------*/
4347 static void genDivbits (operand *left, 
4348                         operand *right, 
4349                         operand *result)
4350 {
4351   char *l;
4352
4353     FENTRY;
4354     /* the result must be bit */    
4355     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4356     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4357
4358     MOVA(l);    
4359
4360     pic16_emitcode("div","ab");
4361     pic16_emitcode("rrc","a");
4362     pic16_aopPut(AOP(result),"c",0);
4363 }
4364
4365 /*-----------------------------------------------------------------*/
4366 /* genDivOneByte : 8 bit division                                  */
4367 /*-----------------------------------------------------------------*/
4368 static void genDivOneByte (operand *left,
4369                            operand *right,
4370                            operand *result)
4371 {
4372   sym_link *opetype = operandType(result);
4373   char *l ;
4374   symbol *lbl ;
4375   int size,offset;
4376
4377         /* result = divident / divisor
4378          * - divident may be a register or a literal,
4379          * - divisor may be a register or a literal,
4380          * so there are 3 cases (literal / literal is optimized
4381          * by the front-end) to handle.
4382          * In addition we must handle signed and unsigned, which
4383          * result in 6 final different cases -- VR */
4384
4385     FENTRY;
4386     
4387     size = AOP_SIZE(result) - 1;
4388     offset = 1;
4389     /* signed or unsigned */
4390     if (SPEC_USIGN(opetype)) {
4391       pCodeOp *pct1,    /* count */
4392                 *pct2,  /* reste */
4393                 *pct3;  /* temp */
4394       symbol *label1, *label2, *label3;;
4395
4396
4397         /* unsigned is easy */
4398
4399         pct1 = pic16_popGetTempReg(1);
4400         pct2 = pic16_popGetTempReg(1);
4401         pct3 = pic16_popGetTempReg(1);
4402         
4403         label1 = newiTempLabel(NULL);
4404         label2 = newiTempLabel(NULL);
4405         label3 = newiTempLabel(NULL);
4406
4407         /* the following algorithm is extracted from divuint.c */
4408
4409         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4410         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4411         
4412         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4413
4414         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4415         
4416         pic16_emitpLabel(label1->key);
4417         
4418         emitCLRC;
4419         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4420
4421
4422         emitCLRC;
4423         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4424         
4425
4426         emitSKPNC;
4427         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4428         
4429         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4430         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4431         
4432         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4433         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4434         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4435         
4436         pic16_emitpLabel( label3->key );
4437         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4438         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4439         
4440         
4441
4442         pic16_emitpLabel(label2->key);
4443         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4444         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4445         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4446         
4447         /* result is in wreg */
4448         if(AOP_TYPE(result) != AOP_ACC)
4449                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4450
4451         pic16_popReleaseTempReg( pct3, 1);
4452         pic16_popReleaseTempReg( pct2, 1);
4453         pic16_popReleaseTempReg( pct1, 1);
4454
4455         return ;
4456     }
4457
4458     /* signed is a little bit more difficult */
4459
4460     /* save the signs of the operands */
4461     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4462     MOVA(l);    
4463     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4464     pic16_emitcode("push","acc"); /* save it on the stack */
4465
4466     /* now sign adjust for both left & right */
4467     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4468     MOVA(l);       
4469     lbl = newiTempLabel(NULL);
4470     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4471     pic16_emitcode("cpl","a");   
4472     pic16_emitcode("inc","a");
4473     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4474     pic16_emitcode("mov","b,a");
4475
4476     /* sign adjust left side */
4477     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4478     MOVA(l);
4479
4480     lbl = newiTempLabel(NULL);
4481     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4482     pic16_emitcode("cpl","a");
4483     pic16_emitcode("inc","a");
4484     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4485
4486     /* now the division */
4487     pic16_emitcode("div","ab");
4488     /* we are interested in the lower order
4489     only */
4490     pic16_emitcode("mov","b,a");
4491     lbl = newiTempLabel(NULL);
4492     pic16_emitcode("pop","acc");   
4493     /* if there was an over flow we don't 
4494     adjust the sign of the result */
4495     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4496     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4497     CLRC;
4498     pic16_emitcode("clr","a");
4499     pic16_emitcode("subb","a,b");
4500     pic16_emitcode("mov","b,a");
4501     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4502
4503     /* now we are done */
4504     pic16_aopPut(AOP(result),"b",0);
4505     if(size > 0){
4506         pic16_emitcode("mov","c,b.7");
4507         pic16_emitcode("subb","a,acc");   
4508     }
4509     while (size--)
4510         pic16_aopPut(AOP(result),"a",offset++);
4511
4512 }
4513
4514 /*-----------------------------------------------------------------*/
4515 /* genDiv - generates code for division                            */
4516 /*-----------------------------------------------------------------*/
4517 static void genDiv (iCode *ic)
4518 {
4519     operand *left = IC_LEFT(ic);
4520     operand *right = IC_RIGHT(ic);
4521     operand *result= IC_RESULT(ic);   
4522
4523
4524         /* Division is a very lengthy algorithm, so it is better
4525          * to call support routines than inlining algorithm.
4526          * Division functions written here just in case someone
4527          * wants to inline and not use the support libraries -- VR */
4528
4529     FENTRY;
4530     
4531     /* assign the amsops */
4532     pic16_aopOp (left,ic,FALSE);
4533     pic16_aopOp (right,ic,FALSE);
4534     pic16_aopOp (result,ic,TRUE);
4535
4536     /* special cases first */
4537     /* both are bits */
4538     if (AOP_TYPE(left) == AOP_CRY &&
4539         AOP_TYPE(right)== AOP_CRY) {
4540         genDivbits(left,right,result);
4541         goto release ;
4542     }
4543
4544     /* if both are of size == 1 */
4545     if (AOP_SIZE(left) == 1 &&
4546         AOP_SIZE(right) == 1 ) {
4547         genDivOneByte(left,right,result);
4548         goto release ;
4549     }
4550
4551     /* should have been converted to function call */
4552     assert(0);
4553 release :
4554     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4555     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4556     pic16_freeAsmop(result,NULL,ic,TRUE); 
4557 }
4558
4559 /*-----------------------------------------------------------------*/
4560 /* genModbits :- modulus of bits                                   */
4561 /*-----------------------------------------------------------------*/
4562 static void genModbits (operand *left, 
4563                         operand *right, 
4564                         operand *result)
4565 {
4566   char *l;
4567
4568     FENTRY;  
4569     
4570     werror(W_POSSBUG2, __FILE__, __LINE__);
4571     /* the result must be bit */    
4572     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4573     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4574
4575     MOVA(l);       
4576
4577     pic16_emitcode("div","ab");
4578     pic16_emitcode("mov","a,b");
4579     pic16_emitcode("rrc","a");
4580     pic16_aopPut(AOP(result),"c",0);
4581 }
4582
4583 /*-----------------------------------------------------------------*/
4584 /* genModOneByte : 8 bit modulus                                   */
4585 /*-----------------------------------------------------------------*/
4586 static void genModOneByte (operand *left,
4587                            operand *right,
4588                            operand *result)
4589 {
4590   sym_link *opetype = operandType(result);
4591   char *l ;
4592   symbol *lbl ;
4593
4594     FENTRY;
4595     werror(W_POSSBUG2, __FILE__, __LINE__);
4596
4597     /* signed or unsigned */
4598     if (SPEC_USIGN(opetype)) {
4599         /* unsigned is easy */
4600         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4601         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4602         MOVA(l);    
4603         pic16_emitcode("div","ab");
4604         pic16_aopPut(AOP(result),"b",0);
4605         return ;
4606     }
4607
4608     /* signed is a little bit more difficult */
4609
4610     /* save the signs of the operands */
4611     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4612     MOVA(l);
4613
4614     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4615     pic16_emitcode("push","acc"); /* save it on the stack */
4616
4617     /* now sign adjust for both left & right */
4618     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4619     MOVA(l);
4620
4621     lbl = newiTempLabel(NULL);
4622     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4623     pic16_emitcode("cpl","a");   
4624     pic16_emitcode("inc","a");
4625     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4626     pic16_emitcode("mov","b,a"); 
4627
4628     /* sign adjust left side */
4629     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4630     MOVA(l);
4631
4632     lbl = newiTempLabel(NULL);
4633     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4634     pic16_emitcode("cpl","a");   
4635     pic16_emitcode("inc","a");
4636     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4637
4638     /* now the multiplication */
4639     pic16_emitcode("div","ab");
4640     /* we are interested in the lower order
4641     only */
4642     lbl = newiTempLabel(NULL);
4643     pic16_emitcode("pop","acc");   
4644     /* if there was an over flow we don't 
4645     adjust the sign of the result */
4646     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4647     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4648     CLRC ;
4649     pic16_emitcode("clr","a");
4650     pic16_emitcode("subb","a,b");
4651     pic16_emitcode("mov","b,a");
4652     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4653
4654     /* now we are done */
4655     pic16_aopPut(AOP(result),"b",0);
4656
4657 }
4658
4659 /*-----------------------------------------------------------------*/
4660 /* genMod - generates code for division                            */
4661 /*-----------------------------------------------------------------*/
4662 static void genMod (iCode *ic)
4663 {
4664   operand *left = IC_LEFT(ic);
4665   operand *right = IC_RIGHT(ic);
4666   operand *result= IC_RESULT(ic);  
4667
4668     FENTRY;
4669     
4670     /* assign the amsops */
4671     pic16_aopOp (left,ic,FALSE);
4672     pic16_aopOp (right,ic,FALSE);
4673     pic16_aopOp (result,ic,TRUE);
4674
4675     /* special cases first */
4676     /* both are bits */
4677     if (AOP_TYPE(left) == AOP_CRY &&
4678         AOP_TYPE(right)== AOP_CRY) {
4679         genModbits(left,right,result);
4680         goto release ;
4681     }
4682
4683     /* if both are of size == 1 */
4684     if (AOP_SIZE(left) == 1 &&
4685         AOP_SIZE(right) == 1 ) {
4686         genModOneByte(left,right,result);
4687         goto release ;
4688     }
4689
4690     /* should have been converted to function call */
4691     assert(0);
4692
4693 release :
4694     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4695     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4696     pic16_freeAsmop(result,NULL,ic,TRUE); 
4697 }
4698
4699 /*-----------------------------------------------------------------*/
4700 /* genIfxJump :- will create a jump depending on the ifx           */
4701 /*-----------------------------------------------------------------*/
4702 /*
4703   note: May need to add parameter to indicate when a variable is in bit space.
4704 */
4705 static void genIfxJump (iCode *ic, char *jval)
4706 {
4707   FENTRY;
4708   
4709     /* if true label then we jump if condition
4710     supplied is true */
4711     if ( IC_TRUE(ic) ) {
4712
4713         if(strcmp(jval,"a") == 0)
4714           emitSKPZ;
4715         else if (strcmp(jval,"c") == 0)
4716           emitSKPNC;
4717         else {
4718           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4719           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4720         }
4721
4722         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4723         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4724
4725     }
4726     else {
4727         /* false label is present */
4728         if(strcmp(jval,"a") == 0)
4729           emitSKPNZ;
4730         else if (strcmp(jval,"c") == 0)
4731           emitSKPC;
4732         else {
4733           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4734           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4735         }
4736
4737         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4738         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4739
4740     }
4741
4742
4743     /* mark the icode as generated */
4744     ic->generated = 1;
4745 }
4746
4747 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4748 {
4749   FENTRY;
4750   
4751     /* if true label then we jump if condition
4752     supplied is true */
4753     if ( IC_TRUE(ic) ) {
4754       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4755       pic16_emitpcode(POC_BTFSC, jop);
4756
4757       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4758       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4759
4760     } else {
4761       /* false label is present */
4762       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4763       pic16_emitpcode(POC_BTFSS, jop);
4764           
4765       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4766       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4767     }
4768
4769
4770     /* mark the icode as generated */
4771     ic->generated = 1;
4772 }
4773
4774 #if 0
4775 // not needed ATM
4776
4777 /*-----------------------------------------------------------------*/
4778 /* genSkip                                                         */
4779 /*-----------------------------------------------------------------*/
4780 static void genSkip(iCode *ifx,int status_bit)
4781 {
4782   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4783   if(!ifx)
4784     return;
4785
4786   if ( IC_TRUE(ifx) ) {
4787     switch(status_bit) {
4788     case 'z':
4789       emitSKPNZ;
4790       break;
4791
4792     case 'c':
4793       emitSKPNC;
4794       break;
4795
4796     case 'd':
4797       emitSKPDC;
4798       break;
4799
4800     }
4801
4802     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4803     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4804
4805   } else {
4806
4807     switch(status_bit) {
4808
4809     case 'z':
4810       emitSKPZ;
4811       break;
4812
4813     case 'c':
4814       emitSKPC;
4815       break;
4816
4817     case 'd':
4818       emitSKPDC;
4819       break;
4820     }
4821     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4822     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4823
4824   }
4825
4826 }
4827 #endif
4828
4829 /*-----------------------------------------------------------------*/
4830 /* genSkipc                                                        */
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipc(resolvedIfx *rifx)
4833 {
4834   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4835   
4836   if(!rifx)
4837     return;
4838
4839   if(rifx->condition)
4840     emitSKPC;
4841   else
4842     emitSKPNC;
4843
4844   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4845   rifx->generated = 1;
4846 }
4847
4848 #if !(USE_SIMPLE_GENCMP)
4849 /*-----------------------------------------------------------------*/
4850 /* genSkipz2                                                       */
4851 /*-----------------------------------------------------------------*/
4852 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4853 {
4854   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4855   
4856   if(!rifx)
4857     return;
4858
4859   if( (rifx->condition ^ invert_condition) & 1)
4860     emitSKPZ;
4861   else
4862     emitSKPNZ;
4863
4864   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4865   rifx->generated = 1;
4866 }
4867 #endif
4868
4869 #if 0
4870 /*-----------------------------------------------------------------*/
4871 /* genSkipz                                                        */
4872 /*-----------------------------------------------------------------*/
4873 static void genSkipz(iCode *ifx, int condition)
4874 {
4875   if(!ifx)
4876     return;
4877
4878   if(condition)
4879     emitSKPNZ;
4880   else
4881     emitSKPZ;
4882
4883   if ( IC_TRUE(ifx) )
4884     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4885   else
4886     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4887
4888   if ( IC_TRUE(ifx) )
4889     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4890   else
4891     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4892
4893 }
4894 #endif
4895
4896 #if !(USE_SIMPLE_GENCMP)
4897 /*-----------------------------------------------------------------*/
4898 /* genSkipCond                                                     */
4899 /*-----------------------------------------------------------------*/
4900 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4901 {
4902   if(!rifx)
4903     return;
4904
4905   if(rifx->condition)
4906     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4907   else
4908     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4909
4910
4911   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4912   rifx->generated = 1;
4913 }
4914 #endif
4915
4916 #if 0
4917 /*-----------------------------------------------------------------*/
4918 /* genChkZeroes :- greater or less than comparison                 */
4919 /*     For each byte in a literal that is zero, inclusive or the   */
4920 /*     the corresponding byte in the operand with W                */
4921 /*     returns true if any of the bytes are zero                   */
4922 /*-----------------------------------------------------------------*/
4923 static int genChkZeroes(operand *op, int lit,  int size)
4924 {
4925
4926   int i;
4927   int flag =1;
4928
4929   while(size--) {
4930     i = (lit >> (size*8)) & 0xff;
4931
4932     if(i==0) {
4933       if(flag) 
4934         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4935       else
4936         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4937       flag = 0;
4938     }
4939   }
4940
4941   return (flag==0);
4942 }
4943 #endif
4944
4945
4946 /*-----------------------------------------------------------------*/
4947 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4948 /*                  aop (if it's NOT a literal) or from lit (if    */
4949 /*                  aop is a literal)                              */
4950 /*-----------------------------------------------------------------*/
4951 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4952   if (aop->type == AOP_LIT) {
4953     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4954   } else {
4955     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4956   }
4957 }
4958
4959 /*-----------------------------------------------------------------*/
4960 /* genCmp :- greater or less than comparison                       */
4961 /*-----------------------------------------------------------------*/
4962
4963 #if USE_SIMPLE_GENCMP           /* { */
4964
4965 /* genCmp performs a left < right comparison, stores
4966  * the outcome in result (if != NULL) and generates
4967  * control flow code for the ifx (if != NULL).
4968  *
4969  * This version leaves in sequences like
4970  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4971  * which should be optmized by the peephole
4972  * optimizer - RN 2005-01-01 */
4973 static void genCmp (operand *left,operand *right,
4974                     operand *result, iCode *ifx, int sign)
4975 {
4976   resolvedIfx rIfx;
4977   int size;
4978   int offs;
4979   symbol *templbl;
4980   operand *dummy;
4981   unsigned long lit;
4982   unsigned long mask;
4983   int performedLt;
4984
4985   FENTRY;
4986   
4987   assert (AOP_SIZE(left) == AOP_SIZE(right));
4988   assert (left && right);
4989
4990   size = AOP_SIZE(right) - 1;
4991   mask = (0x100UL << (size*8)) - 1;
4992   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4993   performedLt = 1;
4994   templbl = NULL;
4995   lit = 0;
4996   
4997   resolveIfx (&rIfx, ifx);
4998
4999   /* handle for special cases */
5000   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5001       return;
5002
5003   /**********************************************************************
5004    * handle bits - bit compares are promoted to int compares seemingly! *
5005    **********************************************************************/
5006 #if 0
5007   // THIS IS COMPLETELY UNTESTED!
5008   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5009     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5010     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5011     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5012
5013     emitSETC;
5014     // 1 < {0,1} is false --> clear C by skipping the next instruction
5015     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5016     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5017     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5018     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5019     emitCLRC; // only skipped for left=0 && right=1
5020
5021     goto correct_result_in_carry;
5022   } // if
5023 #endif
5024
5025   /*************************************************
5026    * make sure that left is register (or the like) *
5027    *************************************************/
5028   if (!isAOP_REGlike(left)) {
5029     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5030     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5031     #endif
5032     assert (isAOP_LIT(left));
5033     assert (isAOP_REGlike(right));
5034     // swap left and right
5035     // left < right <==> right > left <==> (right >= left + 1)
5036     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5037
5038     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5039       // MAXVALUE < right? always false
5040       if (performedLt) emitCLRC; else emitSETC;
5041       goto correct_result_in_carry;
5042     } // if
5043
5044     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5045     // that's we handled it above.
5046     lit++;
5047
5048     dummy = left;
5049     left = right;
5050     right = dummy;
5051
5052     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5053   } else if (isAOP_LIT(right)) {
5054     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5055   } // if
5056
5057   assert (isAOP_REGlike(left)); // left must be register or the like
5058   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5059
5060   /*************************************************
5061    * special cases go here                         *
5062    *************************************************/
5063
5064   if (isAOP_LIT(right)) {
5065     if (!sign) {
5066       // unsigned comparison to a literal
5067       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5068       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5069       #endif
5070       if (lit == 0) {
5071         // unsigned left < 0? always false
5072         if (performedLt) emitCLRC; else emitSETC;
5073         goto correct_result_in_carry;
5074       }
5075     } else {
5076       // signed comparison to a literal
5077       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5078       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5079       #endif
5080       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5081         // signed left < 0x80000000? always false
5082         if (performedLt) emitCLRC; else emitSETC;
5083         goto correct_result_in_carry;
5084       } else if (lit == 0) {
5085         // compare left < 0; set CARRY if SIGNBIT(left) is set
5086         if (performedLt) emitSETC; else emitCLRC;
5087         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5088         if (performedLt) emitCLRC; else emitSETC;
5089         goto correct_result_in_carry;
5090       }
5091     } // if (!sign)
5092   } // right is literal
5093
5094   /*************************************************
5095    * perform a general case comparison             *
5096    * make sure we get CARRY==1 <==> left >= right  *
5097    *************************************************/
5098   // compare most significant bytes
5099   //DEBUGpc ("comparing bytes at offset %d", size);
5100   if (!sign) {
5101     // unsigned comparison
5102     mov2w_regOrLit (AOP(right), lit, size);
5103     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5104   } else {
5105     // signed comparison
5106     // (add 2^n to both operands then perform an unsigned comparison)
5107     if (isAOP_LIT(right)) {
5108       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5109       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5110
5111       if (litbyte == 0x80) {
5112         // left >= 0x80 -- always true, but more bytes to come
5113         pic16_mov2w (AOP(left), size);
5114         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5115         emitSETC;
5116       } else {
5117         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5118         pic16_mov2w (AOP(left), size);
5119         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5120         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5121       } // if
5122     } else {
5123       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5124       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5125       pic16_mov2w (AOP(left), size);
5126       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127       pic16_emitpcode (POC_MOVWF, pctemp);
5128       pic16_mov2w (AOP(right), size);
5129       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5130       pic16_emitpcode (POC_SUBFW, pctemp);
5131       //pic16_popReleaseTempReg(pctemp, 1);
5132     }
5133   } // if (!sign)
5134
5135   // compare remaining bytes (treat as unsigned case from above)
5136   templbl = newiTempLabel ( NULL );
5137   offs = size;
5138   while (offs--) {
5139     //DEBUGpc ("comparing bytes at offset %d", offs);
5140     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5141     mov2w_regOrLit (AOP(right), lit, offs);
5142     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5143   } // while (offs)
5144   pic16_emitpLabel (templbl->key);
5145   goto result_in_carry;
5146
5147 result_in_carry:
5148   
5149   /****************************************************
5150    * now CARRY contains the result of the comparison: *
5151    * SUBWF sets CARRY iff                             *
5152    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5153    * (F=left, W=right)
5154    ****************************************************/
5155
5156   if (performedLt) {
5157     if (result && AOP_TYPE(result) != AOP_CRY) {
5158       // value will be stored
5159       emitTOGC;
5160     } else {
5161       // value wil only be used in the following genSkipc()
5162       rIfx.condition ^= 1;
5163     }
5164   } // if
5165
5166 correct_result_in_carry:
5167
5168   // assign result to variable (if neccessary)
5169   if (result && AOP_TYPE(result) != AOP_CRY) {
5170     //DEBUGpc ("assign result");
5171     size = AOP_SIZE(result);
5172     while (size--) {
5173       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5174     } // while
5175     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5176   } // if (result)
5177
5178   // perform conditional jump
5179   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5180   if (ifx) {
5181     //DEBUGpc ("generate control flow");
5182     rIfx.condition ^= 1;
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_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
6173         /* unsigned compare */      
6174         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6175     
6176         compareAopfirstpass=1;
6177         while(size--) {
6178           
6179           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6180           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6181
6182         }
6183
6184         if(ifx)ifx->generated = 1;
6185
6186
6187         if(AOP_SIZE(result)) {
6188           pic16_emitpLabel(falselbl->key);
6189           pic16_outBitC( result );
6190         }
6191
6192       }
6193     } else {
6194       /* compare registers */
6195       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6196
6197
6198       if(sign) {
6199         pCodeOp *pct, *pct2;
6200         
6201         /* signed compare */
6202         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6203
6204         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6205         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6206         tlbl = newiTempLabel( NULL );
6207         
6208         compareAopfirstpass=1;
6209
6210         size--;
6211         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6212 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6213         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214         pic16_emitpcode(POC_MOVWF, pct);
6215
6216         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6217 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219
6220         /* WREG already holds left + 0x80 */
6221         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6222         
6223         while( size-- ) {
6224           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6225 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6226           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6227           pic16_emitpcode(POC_MOVWF, pct);
6228                 
6229           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6230 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6231           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6232
6233           /* WREG already holds left + 0x80 */
6234           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6235 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6236         }
6237         
6238         if(ifx)ifx->generated = 1;
6239
6240         if(AOP_SIZE(result)) {
6241           pic16_emitpLabel(tlbl->key);
6242           pic16_emitpLabel(falselbl->key);
6243           pic16_outBitOp( result, pct2 );
6244         } else {
6245           pic16_emitpLabel(tlbl->key);
6246         }
6247
6248       } else {
6249         /* unsigned compare */      
6250         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6251
6252         compareAopfirstpass=1;
6253         while(size--) {
6254           
6255           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6256           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6257
6258         }
6259
6260         if(ifx)ifx->generated = 1;
6261         if(AOP_SIZE(result)) {
6262
6263           pic16_emitpLabel(falselbl->key);
6264           pic16_outBitC( result );
6265         }
6266
6267       }
6268     }
6269 }
6270
6271 #endif  /* } */
6272
6273
6274
6275 /*-----------------------------------------------------------------*/
6276 /* genCmpGt :- greater than comparison                             */
6277 /*-----------------------------------------------------------------*/
6278 static void genCmpGt (iCode *ic, iCode *ifx)
6279 {
6280   operand *left, *right, *result;
6281   sym_link *letype , *retype;
6282   int sign ;
6283
6284     FENTRY;
6285     
6286     left = IC_LEFT(ic);
6287     right= IC_RIGHT(ic);
6288     result = IC_RESULT(ic);
6289
6290     letype = getSpec(operandType(left));
6291     retype =getSpec(operandType(right));
6292     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6293     /* assign the amsops */
6294     pic16_aopOp (left,ic,FALSE);
6295     pic16_aopOp (right,ic,FALSE);
6296     pic16_aopOp (result,ic,TRUE);
6297
6298     genCmp(right, left, result, ifx, sign);
6299
6300     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6301     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6302     pic16_freeAsmop(result,NULL,ic,TRUE); 
6303 }
6304
6305 /*-----------------------------------------------------------------*/
6306 /* genCmpLt - less than comparisons                                */
6307 /*-----------------------------------------------------------------*/
6308 static void genCmpLt (iCode *ic, iCode *ifx)
6309 {
6310   operand *left, *right, *result;
6311   sym_link *letype , *retype;
6312   int sign ;
6313
6314     FENTRY;
6315
6316     left = IC_LEFT(ic);
6317     right= IC_RIGHT(ic);
6318     result = IC_RESULT(ic);
6319
6320     letype = getSpec(operandType(left));
6321     retype =getSpec(operandType(right));
6322     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6323
6324     /* assign the amsops */
6325     pic16_aopOp (left,ic,FALSE);
6326     pic16_aopOp (right,ic,FALSE);
6327     pic16_aopOp (result,ic,TRUE);
6328
6329     genCmp(left, right, result, ifx, sign);
6330
6331     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6332     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6333     pic16_freeAsmop(result,NULL,ic,TRUE); 
6334 }
6335
6336 #if 0
6337 // not needed ATM
6338 // FIXME reenable literal optimisation when the pic16 port is stable
6339
6340 /*-----------------------------------------------------------------*/
6341 /* genc16bit2lit - compare a 16 bit value to a literal             */
6342 /*-----------------------------------------------------------------*/
6343 static void genc16bit2lit(operand *op, int lit, int offset)
6344 {
6345   int i;
6346
6347   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6348   if( (lit&0xff) == 0) 
6349     i=1;
6350   else
6351     i=0;
6352
6353   switch( BYTEofLONG(lit,i)) { 
6354   case 0:
6355     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6356     break;
6357   case 1:
6358     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6359     break;
6360   case 0xff:
6361     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6362     break;
6363   default:
6364     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6365     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6366   }
6367
6368   i ^= 1;
6369
6370   switch( BYTEofLONG(lit,i)) { 
6371   case 0:
6372     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6373     break;
6374   case 1:
6375     emitSKPNZ;
6376     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6377     break;
6378   case 0xff:
6379     emitSKPNZ;
6380     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6381     break;
6382   default:
6383     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6384     emitSKPNZ;
6385     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6386
6387   }
6388
6389 }
6390 #endif
6391
6392 #if 0
6393 // not needed ATM
6394 /*-----------------------------------------------------------------*/
6395 /* gencjneshort - compare and jump if not equal                    */
6396 /*-----------------------------------------------------------------*/
6397 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6398 {
6399   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6400   int offset = 0;
6401   int res_offset = 0;  /* the result may be a different size then left or right */
6402   int res_size = AOP_SIZE(result);
6403   resolvedIfx rIfx;
6404   symbol *lbl, *lbl_done;
6405
6406   unsigned long lit = 0L;
6407   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6408
6409   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6410   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6411   if(result)
6412     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6413   resolveIfx(&rIfx,ifx);
6414   lbl =  newiTempLabel(NULL);
6415   lbl_done =  newiTempLabel(NULL);
6416
6417
6418   /* if the left side is a literal or 
6419      if the right is in a pointer register and left 
6420      is not */
6421   if ((AOP_TYPE(left) == AOP_LIT) || 
6422       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6423     operand *t = right;
6424     right = left;
6425     left = t;
6426   }
6427   if(AOP_TYPE(right) == AOP_LIT)
6428     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6429
6430   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6431     preserve_result = 1;
6432
6433   if(result && !preserve_result)
6434     {
6435       int i;
6436       for(i = 0; i < AOP_SIZE(result); i++)
6437         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6438     }
6439
6440
6441   /* if the right side is a literal then anything goes */
6442   if (AOP_TYPE(right) == AOP_LIT &&
6443       AOP_TYPE(left) != AOP_DIR ) {
6444     switch(size) {
6445     case 2:
6446       genc16bit2lit(left, lit, 0);
6447       emitSKPZ;
6448       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6449       break;
6450     default:
6451       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6452       while (size--) {
6453         if(lit & 0xff) {
6454           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6455           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6456         } else {
6457           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6458         }
6459
6460         emitSKPZ;
6461         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6462         offset++;
6463         if(res_offset < res_size-1)
6464           res_offset++;
6465         lit >>= 8;
6466       }
6467       break;
6468     }
6469   }
6470
6471   /* if the right side is in a register or in direct space or
6472      if the left is a pointer register & right is not */    
6473   else if (AOP_TYPE(right) == AOP_REG ||
6474            AOP_TYPE(right) == AOP_DIR || 
6475            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6476            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6477     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6478     int lbl_key = lbl->key;
6479
6480     if(result) {
6481       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6482       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6483     }else {
6484       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6485       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6486               __FUNCTION__,__LINE__);
6487       return;
6488     }
6489    
6490 /*     switch(size) { */
6491 /*     case 2: */
6492 /*       genc16bit2lit(left, lit, 0); */
6493 /*       emitSKPNZ; */
6494 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6495 /*       break; */
6496 /*     default: */
6497     while (size--) {
6498       int emit_skip=1;
6499       if((AOP_TYPE(left) == AOP_DIR) && 
6500          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6501
6502         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6503         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6504
6505       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6506             
6507         switch (lit & 0xff) {
6508         case 0:
6509           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6510           break;
6511         case 1:
6512           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6513           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6515           emit_skip=0;
6516           break;
6517         case 0xff:
6518           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6519           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6520           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6521           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6522           emit_skip=0;
6523           break;
6524         default:
6525           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6526           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6527         }
6528         lit >>= 8;
6529
6530       } else {
6531         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6532       }
6533       if(emit_skip) {
6534         if(AOP_TYPE(result) == AOP_CRY) {
6535           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6536           if(rIfx.condition)
6537             emitSKPNZ;
6538           else
6539             emitSKPZ;
6540           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6541         } else {
6542           /* fix me. probably need to check result size too */
6543           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6544           if(rIfx.condition)
6545             emitSKPZ;
6546           else
6547             emitSKPNZ;
6548           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6549           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6550         }
6551         if(ifx)
6552           ifx->generated=1;
6553       }
6554       emit_skip++;
6555       offset++;
6556       if(res_offset < res_size-1)
6557         res_offset++;
6558     }
6559 /*       break; */
6560 /*     } */
6561   } else if(AOP_TYPE(right) == AOP_REG &&
6562             AOP_TYPE(left) != AOP_DIR){
6563
6564     while(size--) {
6565       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6566       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6567       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6568       if(rIfx.condition)
6569         emitSKPNZ;
6570       else
6571         emitSKPZ;
6572       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6573       offset++;
6574       if(res_offset < res_size-1)
6575         res_offset++;
6576     }
6577       
6578   }else{
6579     /* right is a pointer reg need both a & b */
6580     while(size--) {
6581       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6582       if(strcmp(l,"b"))
6583         pic16_emitcode("mov","b,%s",l);
6584       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6585       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6586       offset++;
6587     }
6588   }
6589
6590   if(result && preserve_result)
6591     {
6592       int i;
6593       for(i = 0; i < AOP_SIZE(result); i++)
6594         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6595     }
6596
6597   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6598
6599   if(result && preserve_result)
6600     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6601
6602   if(!rIfx.condition)
6603     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6604
6605   pic16_emitpLabel(lbl->key);
6606
6607   if(result && preserve_result)
6608     {
6609       int i;
6610       for(i = 0; i < AOP_SIZE(result); i++)
6611         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6612
6613       pic16_emitpLabel(lbl_done->key);
6614    }
6615
6616   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6617
6618   if(ifx)
6619     ifx->generated = 1;
6620 }
6621 #endif
6622
6623 #if 0
6624 /*-----------------------------------------------------------------*/
6625 /* gencjne - compare and jump if not equal                         */
6626 /*-----------------------------------------------------------------*/
6627 static void gencjne(operand *left, operand *right, iCode *ifx)
6628 {
6629     symbol *tlbl  = newiTempLabel(NULL);
6630
6631     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6632     gencjneshort(left, right, lbl);
6633
6634     pic16_emitcode("mov","a,%s",one);
6635     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6636     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6637     pic16_emitcode("clr","a");
6638     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6639
6640     pic16_emitpLabel(lbl->key);
6641     pic16_emitpLabel(tlbl->key);
6642
6643 }
6644 #endif
6645
6646
6647 /*-----------------------------------------------------------------*/
6648 /* is_LitOp - check if operand has to be treated as literal        */
6649 /*-----------------------------------------------------------------*/
6650 static bool is_LitOp(operand *op)
6651 {
6652   return ((AOP_TYPE(op) == AOP_LIT)
6653       || ( (AOP_TYPE(op) == AOP_PCODE)
6654           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6655               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6656 }
6657
6658 /*-----------------------------------------------------------------*/
6659 /* is_LitAOp - check if operand has to be treated as literal        */
6660 /*-----------------------------------------------------------------*/
6661 static bool is_LitAOp(asmop *aop)
6662 {
6663   return ((aop->type == AOP_LIT)
6664       || ( (aop->type == AOP_PCODE)
6665           && ( (aop->aopu.pcop->type == PO_LITERAL)
6666               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6667 }
6668
6669
6670
6671 /*-----------------------------------------------------------------*/
6672 /* genCmpEq - generates code for equal to                          */
6673 /*-----------------------------------------------------------------*/
6674 static void genCmpEq (iCode *ic, iCode *ifx)
6675 {
6676   operand *left, *right, *result;
6677   symbol *falselbl = newiTempLabel(NULL);
6678   symbol *donelbl = newiTempLabel(NULL);
6679
6680   int preserve_result = 0;
6681   int generate_result = 0;
6682   int i=0;
6683   unsigned long lit = -1;
6684
6685   FENTRY;
6686   
6687   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6688   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6689   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6690  
6691   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6692
6693   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6694     {
6695       werror(W_POSSBUG2, __FILE__, __LINE__);
6696       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6697       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6698       goto release;
6699     }
6700
6701   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6702     {
6703       operand *tmp = right ;
6704       right = left;
6705       left = tmp;
6706     }
6707
6708   if (AOP_TYPE(right) == AOP_LIT) {
6709     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6710   }
6711
6712   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6713     preserve_result = 1;
6714
6715   if(result && AOP_SIZE(result))
6716     generate_result = 1;
6717
6718   if(generate_result && !preserve_result)
6719     {
6720       for(i = 0; i < AOP_SIZE(result); i++)
6721         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6722     }
6723
6724   for(i=0; i < AOP_SIZE(left); i++)
6725     {
6726       if(AOP_TYPE(left) != AOP_ACC)
6727         {
6728           if(is_LitOp(left))
6729             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6730           else
6731             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6732         }
6733       if(is_LitOp(right)) {
6734         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6735           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6736         }
6737       } else
6738         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6739
6740       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6741     }
6742
6743   // result == true
6744
6745   if(generate_result && preserve_result)
6746     {
6747       for(i = 0; i < AOP_SIZE(result); i++)
6748         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6749     }
6750
6751   if(generate_result)
6752     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6753
6754   if(generate_result && preserve_result)
6755     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6756
6757   if(ifx && IC_TRUE(ifx))
6758     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6759
6760   if(ifx && IC_FALSE(ifx))
6761     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6762
6763   pic16_emitpLabel(falselbl->key);
6764
6765   // result == false
6766
6767   if(ifx && IC_FALSE(ifx))
6768     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6769
6770   if(generate_result && preserve_result)
6771     {
6772       for(i = 0; i < AOP_SIZE(result); i++)
6773         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6774     }
6775
6776   pic16_emitpLabel(donelbl->key);
6777
6778   if(ifx)
6779     ifx->generated = 1;
6780
6781 release:
6782   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6783   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6784   pic16_freeAsmop(result,NULL,ic,TRUE);
6785
6786 }
6787
6788
6789 #if 0
6790 // old version kept for reference
6791
6792 /*-----------------------------------------------------------------*/
6793 /* genCmpEq - generates code for equal to                          */
6794 /*-----------------------------------------------------------------*/
6795 static void genCmpEq (iCode *ic, iCode *ifx)
6796 {
6797     operand *left, *right, *result;
6798     unsigned long lit = 0L;
6799     int size,offset=0;
6800     symbol *falselbl  = newiTempLabel(NULL);
6801
6802
6803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6804
6805     if(ifx)
6806       DEBUGpic16_emitcode ("; ifx is non-null","");
6807     else
6808       DEBUGpic16_emitcode ("; ifx is null","");
6809
6810     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6811     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6812     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6813
6814     size = max(AOP_SIZE(left),AOP_SIZE(right));
6815
6816     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6817
6818     /* if literal, literal on the right or 
6819     if the right is in a pointer register and left 
6820     is not */
6821     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6822         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6823       operand *tmp = right ;
6824       right = left;
6825       left = tmp;
6826     }
6827
6828
6829     if(ifx && !AOP_SIZE(result)){
6830         symbol *tlbl;
6831         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6832         /* if they are both bit variables */
6833         if (AOP_TYPE(left) == AOP_CRY &&
6834             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6835                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6836             if(AOP_TYPE(right) == AOP_LIT){
6837                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6838                 if(lit == 0L){
6839                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840                     pic16_emitcode("cpl","c");
6841                 } else if(lit == 1L) {
6842                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6843                 } else {
6844                     pic16_emitcode("clr","c");
6845                 }
6846                 /* AOP_TYPE(right) == AOP_CRY */
6847             } else {
6848                 symbol *lbl = newiTempLabel(NULL);
6849                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6850                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6851                 pic16_emitcode("cpl","c");
6852                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6853             }
6854             /* if true label then we jump if condition
6855             supplied is true */
6856             tlbl = newiTempLabel(NULL);
6857             if ( IC_TRUE(ifx) ) {
6858                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6859                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6860             } else {
6861                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6862                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6863             }
6864             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6865
6866                 {
6867                 /* left and right are both bit variables, result is carry */
6868                         resolvedIfx rIfx;
6869               
6870                         resolveIfx(&rIfx,ifx);
6871
6872                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6873                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6874                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6875                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6876                         genSkipz2(&rIfx,0);
6877                 }
6878         } else {
6879
6880                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6881
6882                         /* They're not both bit variables. Is the right a literal? */
6883                         if(AOP_TYPE(right) == AOP_LIT) {
6884                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6885             
6886                         switch(size) {
6887
6888                                 case 1:
6889                                         switch(lit & 0xff) {
6890                                                 case 1:
6891                                                                 if ( IC_TRUE(ifx) ) {
6892                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6893                                                                         emitSKPNZ;
6894                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6895                                                                 } else {
6896                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6897                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6898                                                                 }
6899                                                                 break;
6900                                                 case 0xff:
6901                                                                 if ( IC_TRUE(ifx) ) {
6902                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6903                                                                         emitSKPNZ;
6904                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6905                                                                 } else {
6906                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6907                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6908                                                                 }
6909                                                                 break;
6910                                                 default:
6911                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6912                                                                 if(lit)
6913                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6914                                                                 genSkip(ifx,'z');
6915                                         } // switch lit
6916
6917
6918                                         /* end of size == 1 */
6919                                         break;
6920               
6921                                 case 2:
6922                                         genc16bit2lit(left,lit,offset);
6923                                         genSkip(ifx,'z');
6924                                         break;
6925                                         /* end of size == 2 */
6926
6927                                 default:
6928                                         /* size is 4 */
6929                                         if(lit==0) {
6930                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6931                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6932                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6933                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6934                                                 genSkip(ifx,'z');
6935                                         } else {
6936                                                 /* search for patterns that can be optimized */
6937
6938                                                 genc16bit2lit(left,lit,0);
6939                                                 lit >>= 16;
6940                                                 if(lit) {
6941                                                                 if(IC_TRUE(ifx))
6942                                                                 emitSKPZ; // if hi word unequal
6943                                                                 else
6944                                                                 emitSKPNZ; // if hi word equal
6945                                                                 // fail early
6946                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6947                                                         genc16bit2lit(left,lit,2);
6948                                                         genSkip(ifx,'z');
6949                                                 } else {
6950                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6951                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6952                                                         genSkip(ifx,'z');
6953                                                 }
6954                                         }
6955                                                 pic16_emitpLabel(falselbl->key);
6956                                                 break;
6957
6958                         } // switch size
6959           
6960                         ifx->generated = 1;
6961                         goto release ;
6962             
6963
6964           } else if(AOP_TYPE(right) == AOP_CRY ) {
6965             /* we know the left is not a bit, but that the right is */
6966             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6967             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6968                       pic16_popGet(AOP(right),offset));
6969             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6970
6971             /* if the two are equal, then W will be 0 and the Z bit is set
6972              * we could test Z now, or go ahead and check the high order bytes if
6973              * the variable we're comparing is larger than a byte. */
6974
6975             while(--size)
6976               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6977
6978             if ( IC_TRUE(ifx) ) {
6979               emitSKPNZ;
6980               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6981               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6982             } else {
6983               emitSKPZ;
6984               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6985               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6986             }
6987
6988           } else {
6989             /* They're both variables that are larger than bits */
6990             int s = size;
6991
6992             tlbl = newiTempLabel(NULL);
6993
6994             while(size--) {
6995               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6996               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6997
6998               if ( IC_TRUE(ifx) ) {
6999                 if(size) {
7000                   emitSKPZ;
7001                 
7002                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7003
7004                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7005                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7006                 } else {
7007                   emitSKPNZ;
7008
7009                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7010
7011
7012                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7013                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7014                 }
7015               } else {
7016                 emitSKPZ;
7017
7018                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7019
7020                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7021                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7022               }
7023               offset++;
7024             }
7025             if(s>1 && IC_TRUE(ifx)) {
7026               pic16_emitpLabel(tlbl->key);
7027               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7028             }
7029           }
7030         }
7031         /* mark the icode as generated */
7032         ifx->generated = 1;
7033         goto release ;
7034     }
7035
7036     /* if they are both bit variables */
7037     if (AOP_TYPE(left) == AOP_CRY &&
7038         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7039         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7040         if(AOP_TYPE(right) == AOP_LIT){
7041             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7042             if(lit == 0L){
7043                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044                 pic16_emitcode("cpl","c");
7045             } else if(lit == 1L) {
7046                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7047             } else {
7048                 pic16_emitcode("clr","c");
7049             }
7050             /* AOP_TYPE(right) == AOP_CRY */
7051         } else {
7052             symbol *lbl = newiTempLabel(NULL);
7053             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7054             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7055             pic16_emitcode("cpl","c");
7056             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7057         }
7058         /* c = 1 if egal */
7059         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7060             pic16_outBitC(result);
7061             goto release ;
7062         }
7063         if (ifx) {
7064             genIfxJump (ifx,"c");
7065             goto release ;
7066         }
7067         /* if the result is used in an arithmetic operation
7068         then put the result in place */
7069         pic16_outBitC(result);
7070     } else {
7071       
7072       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7073       gencjne(left,right,result,ifx);
7074 /*
7075       if(ifx) 
7076         gencjne(left,right,newiTempLabel(NULL));
7077       else {
7078         if(IC_TRUE(ifx)->key)
7079           gencjne(left,right,IC_TRUE(ifx)->key);
7080         else
7081           gencjne(left,right,IC_FALSE(ifx)->key);
7082         ifx->generated = 1;
7083         goto release ;
7084       }
7085       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7086         pic16_aopPut(AOP(result),"a",0);
7087         goto release ;
7088       }
7089
7090       if (ifx) {
7091         genIfxJump (ifx,"a");
7092         goto release ;
7093       }
7094 */
7095       /* if the result is used in an arithmetic operation
7096          then put the result in place */
7097 /*
7098       if (AOP_TYPE(result) != AOP_CRY) 
7099         pic16_outAcc(result);
7100 */
7101       /* leave the result in acc */
7102     }
7103
7104 release:
7105     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7106     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7107     pic16_freeAsmop(result,NULL,ic,TRUE);
7108 }
7109 #endif
7110
7111 /*-----------------------------------------------------------------*/
7112 /* ifxForOp - returns the icode containing the ifx for operand     */
7113 /*-----------------------------------------------------------------*/
7114 static iCode *ifxForOp ( operand *op, iCode *ic )
7115 {
7116   FENTRY2;
7117
7118     /* if true symbol then needs to be assigned */
7119     if (IS_TRUE_SYMOP(op))
7120         return NULL ;
7121
7122     /* if this has register type condition and
7123     the next instruction is ifx with the same operand
7124     and live to of the operand is upto the ifx only then */
7125     if (ic->next
7126         && ic->next->op == IFX
7127         && IC_COND(ic->next)->key == op->key
7128         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7129         ) {
7130                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7131           return ic->next;
7132     }
7133
7134     /*
7135     if (ic->next &&
7136         ic->next->op == IFX &&
7137         IC_COND(ic->next)->key == op->key) {
7138       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7139       return ic->next;
7140     }
7141     */
7142
7143     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7144     if (ic->next &&
7145         ic->next->op == IFX)
7146       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7147
7148     if (ic->next &&
7149         ic->next->op == IFX &&
7150         IC_COND(ic->next)->key == op->key) {
7151       DEBUGpic16_emitcode ("; "," key is okay");
7152       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7153                            OP_SYMBOL(op)->liveTo,
7154                            ic->next->seq);
7155     }
7156
7157 #if 0
7158     /* the code below is completely untested
7159      * it just allows ulong2fs.c compile -- VR */
7160          
7161     ic = ic->next;
7162     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7163                                         __FILE__, __FUNCTION__, __LINE__);
7164         
7165     /* if this has register type condition and
7166     the next instruction is ifx with the same operand
7167     and live to of the operand is upto the ifx only then */
7168     if (ic->next &&
7169         ic->next->op == IFX &&
7170         IC_COND(ic->next)->key == op->key &&
7171         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7172         return ic->next;
7173
7174     if (ic->next &&
7175         ic->next->op == IFX &&
7176         IC_COND(ic->next)->key == op->key) {
7177       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7178       return ic->next;
7179     }
7180
7181     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7182                                         __FILE__, __FUNCTION__, __LINE__);
7183
7184 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7185 #endif
7186
7187     return NULL;
7188 }
7189 /*-----------------------------------------------------------------*/
7190 /* genAndOp - for && operation                                     */
7191 /*-----------------------------------------------------------------*/
7192 static void genAndOp (iCode *ic)
7193 {
7194   operand *left,*right, *result;
7195 /*     symbol *tlbl; */
7196
7197     FENTRY;
7198
7199     /* note here that && operations that are in an
7200     if statement are taken away by backPatchLabels
7201     only those used in arthmetic operations remain */
7202     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7203     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7204     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7205
7206     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7207
7208     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7209     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7210     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7211
7212     /* if both are bit variables */
7213 /*     if (AOP_TYPE(left) == AOP_CRY && */
7214 /*         AOP_TYPE(right) == AOP_CRY ) { */
7215 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7216 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7217 /*         pic16_outBitC(result); */
7218 /*     } else { */
7219 /*         tlbl = newiTempLabel(NULL); */
7220 /*         pic16_toBoolean(left);     */
7221 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7222 /*         pic16_toBoolean(right); */
7223 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7224 /*         pic16_outBitAcc(result); */
7225 /*     } */
7226
7227     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7228     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7229     pic16_freeAsmop(result,NULL,ic,TRUE);
7230 }
7231
7232
7233 /*-----------------------------------------------------------------*/
7234 /* genOrOp - for || operation                                      */
7235 /*-----------------------------------------------------------------*/
7236 /*
7237   tsd pic port -
7238   modified this code, but it doesn't appear to ever get called
7239 */
7240
7241 static void genOrOp (iCode *ic)
7242 {
7243   operand *left,*right, *result;
7244   symbol *tlbl;
7245
7246     FENTRY;  
7247
7248   /* note here that || operations that are in an
7249     if statement are taken away by backPatchLabels
7250     only those used in arthmetic operations remain */
7251     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7252     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7253     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7254
7255     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7256
7257     /* if both are bit variables */
7258     if (AOP_TYPE(left) == AOP_CRY &&
7259         AOP_TYPE(right) == AOP_CRY ) {
7260       pic16_emitcode("clrc","");
7261       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7262                AOP(left)->aopu.aop_dir,
7263                AOP(left)->aopu.aop_dir);
7264       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7265                AOP(right)->aopu.aop_dir,
7266                AOP(right)->aopu.aop_dir);
7267       pic16_emitcode("setc","");
7268
7269     } else {
7270         tlbl = newiTempLabel(NULL);
7271         pic16_toBoolean(left);
7272         emitSKPZ;
7273         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7274         pic16_toBoolean(right);
7275         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7276
7277         pic16_outBitAcc(result);
7278     }
7279
7280     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7281     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7282     pic16_freeAsmop(result,NULL,ic,TRUE);            
7283 }
7284
7285 /*-----------------------------------------------------------------*/
7286 /* isLiteralBit - test if lit == 2^n                               */
7287 /*-----------------------------------------------------------------*/
7288 static int isLiteralBit(unsigned long lit)
7289 {
7290     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7291     0x100L,0x200L,0x400L,0x800L,
7292     0x1000L,0x2000L,0x4000L,0x8000L,
7293     0x10000L,0x20000L,0x40000L,0x80000L,
7294     0x100000L,0x200000L,0x400000L,0x800000L,
7295     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7296     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7297     int idx;
7298     
7299     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7300     for(idx = 0; idx < 32; idx++)
7301         if(lit == pw[idx])
7302             return idx+1;
7303     return 0;
7304 }
7305
7306 /*-----------------------------------------------------------------*/
7307 /* continueIfTrue -                                                */
7308 /*-----------------------------------------------------------------*/
7309 static void continueIfTrue (iCode *ic)
7310 {
7311   FENTRY;
7312   if(IC_TRUE(ic))
7313     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7314   ic->generated = 1;
7315 }
7316
7317 /*-----------------------------------------------------------------*/
7318 /* jmpIfTrue -                                                     */
7319 /*-----------------------------------------------------------------*/
7320 static void jumpIfTrue (iCode *ic)
7321 {
7322   FENTRY;
7323   if(!IC_TRUE(ic))
7324     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7325   ic->generated = 1;
7326 }
7327
7328 /*-----------------------------------------------------------------*/
7329 /* jmpTrueOrFalse -                                                */
7330 /*-----------------------------------------------------------------*/
7331 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7332 {
7333   // ugly but optimized by peephole
7334   FENTRY;
7335   if(IC_TRUE(ic)){
7336     symbol *nlbl = newiTempLabel(NULL);
7337       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7338       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7339       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7340       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7341   } else {
7342     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7343     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7344   }
7345   ic->generated = 1;
7346 }
7347
7348 /*-----------------------------------------------------------------*/
7349 /* genAnd  - code for and                                          */
7350 /*-----------------------------------------------------------------*/
7351 static void genAnd (iCode *ic, iCode *ifx)
7352 {
7353   operand *left, *right, *result;
7354   int size, offset=0;  
7355   unsigned long lit = 0L;
7356   int bytelit = 0;
7357   resolvedIfx rIfx;
7358
7359     FENTRY;
7360     
7361   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7362   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7363   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7364
7365   resolveIfx(&rIfx,ifx);
7366
7367   /* if left is a literal & right is not then exchange them */
7368   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7369       AOP_NEEDSACC(left)) {
7370     operand *tmp = right ;
7371     right = left;
7372     left = tmp;
7373   }
7374
7375   /* if result = right then exchange them */
7376   if(pic16_sameRegs(AOP(result),AOP(right))){
7377     operand *tmp = right ;
7378     right = left;
7379     left = tmp;
7380   }
7381
7382   /* if right is bit then exchange them */
7383   if (AOP_TYPE(right) == AOP_CRY &&
7384       AOP_TYPE(left) != AOP_CRY){
7385     operand *tmp = right ;
7386     right = left;
7387     left = tmp;
7388   }
7389   if(AOP_TYPE(right) == AOP_LIT)
7390     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7391
7392   size = AOP_SIZE(result);
7393
7394   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7395
7396   // if(bit & yy)
7397   // result = bit & yy;
7398   if (AOP_TYPE(left) == AOP_CRY){
7399     // c = bit & literal;
7400     if(AOP_TYPE(right) == AOP_LIT){
7401       if(lit & 1) {
7402         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7403           // no change
7404           goto release;
7405         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7406       } else {
7407         // bit(result) = 0;
7408         if(size && (AOP_TYPE(result) == AOP_CRY)){
7409           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7410           goto release;
7411         }
7412         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7413           jumpIfTrue(ifx);
7414           goto release;
7415         }
7416         pic16_emitcode("clr","c");
7417       }
7418     } else {
7419       if (AOP_TYPE(right) == AOP_CRY){
7420         // c = bit & bit;
7421         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7422         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7423       } else {
7424         // c = bit & val;
7425         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7426         // c = lsb
7427         pic16_emitcode("rrc","a");
7428         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7429       }
7430     }
7431     // bit = c
7432     // val = c
7433     if(size)
7434       pic16_outBitC(result);
7435     // if(bit & ...)
7436     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7437       genIfxJump(ifx, "c");           
7438     goto release ;
7439   }
7440
7441   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7442   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7443   if((AOP_TYPE(right) == AOP_LIT) &&
7444      (AOP_TYPE(result) == AOP_CRY) &&
7445      (AOP_TYPE(left) != AOP_CRY)){
7446     int posbit = isLiteralBit(lit);
7447     /* left &  2^n */
7448     if(posbit){
7449       posbit--;
7450       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7451       // bit = left & 2^n
7452       if(size)
7453         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7454       // if(left &  2^n)
7455       else{
7456         if(ifx){
7457 /*
7458           if(IC_TRUE(ifx)) {
7459             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7461           } else {
7462             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7463             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7464           }
7465 */
7466         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7467         size = AOP_SIZE(left);
7468
7469         {
7470           int bp = posbit, ofs=0;
7471           
7472             while(bp > 7) {
7473               bp -= 8;
7474               ofs++;
7475             }
7476         
7477           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7478                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7479
7480         }
7481 /*
7482           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7483                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7484 */
7485           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7486           
7487           ifx->generated = 1;
7488         }
7489         goto release;
7490       }
7491     } else {
7492       symbol *tlbl = newiTempLabel(NULL);
7493       int sizel = AOP_SIZE(left);
7494
7495       if(size)
7496         emitSETC;
7497
7498       while(sizel--) {
7499         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7500
7501           /* patch provided by Aaron Colwell */
7502           if((posbit = isLiteralBit(bytelit)) != 0) {
7503               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7504                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7505                                                 (posbit-1),0, PO_GPR_REGISTER));
7506
7507               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7508 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7509           } else {
7510               if (bytelit == 0xff) {
7511                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7512                    * a peephole could optimize it out -- VR */
7513                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7514               } else {
7515                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7516                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7517               }
7518
7519               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7520                             pic16_popGetLabel(tlbl->key));
7521           }
7522         
7523 #if 0
7524           /* old code, left here for reference -- VR 09/2004 */
7525           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7526           // byte ==  2^n ?
7527           if((posbit = isLiteralBit(bytelit)) != 0)
7528             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7529           else{
7530             if(bytelit != 0x0FFL)
7531               pic16_emitcode("anl","a,%s",
7532                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7533             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7534           }
7535 #endif
7536         }
7537         offset++;
7538       }
7539       // bit = left & literal
7540       if(size) {
7541         emitCLRC;
7542         pic16_emitpLabel(tlbl->key);
7543       }
7544       // if(left & literal)
7545       else {
7546         if(ifx) {
7547           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7548           ifx->generated = 1;
7549         }
7550         pic16_emitpLabel(tlbl->key);
7551         goto release;
7552       }
7553     }
7554
7555     pic16_outBitC(result);
7556     goto release ;
7557   }
7558
7559   /* if left is same as result */
7560   if(pic16_sameRegs(AOP(result),AOP(left))){
7561     int know_W = -1;
7562     for(;size--; offset++,lit>>=8) {
7563       if(AOP_TYPE(right) == AOP_LIT){
7564         switch(lit & 0xff) {
7565         case 0x00:
7566           /*  and'ing with 0 has clears the result */
7567 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7568           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7569           break;
7570         case 0xff:
7571           /* and'ing with 0xff is a nop when the result and left are the same */
7572           break;
7573
7574         default:
7575           {
7576             int p = pic16_my_powof2( (~lit) & 0xff );
7577             if(p>=0) {
7578               /* only one bit is set in the literal, so use a bcf instruction */
7579 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7580               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7581
7582             } else {
7583               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7584               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7585               if(know_W != (lit&0xff))
7586                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7587               know_W = lit &0xff;
7588               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7589             }
7590           }    
7591         }
7592       } else {
7593         if (AOP_TYPE(left) == AOP_ACC) {
7594           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7595         } else {                    
7596           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7597           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7598
7599         }
7600       }
7601     }
7602
7603   } else {
7604     // left & result in different registers
7605     if(AOP_TYPE(result) == AOP_CRY){
7606       // result = bit
7607       // if(size), result in bit
7608       // if(!size && ifx), conditional oper: if(left & right)
7609       symbol *tlbl = newiTempLabel(NULL);
7610       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7611       if(size)
7612         pic16_emitcode("setb","c");
7613       while(sizer--){
7614         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7615         pic16_emitcode("anl","a,%s",
7616                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7617         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7618         offset++;
7619       }
7620       if(size){
7621         CLRC;
7622         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7623         pic16_outBitC(result);
7624       } else if(ifx)
7625         jmpTrueOrFalse(ifx, tlbl);
7626     } else {
7627       for(;(size--);offset++) {
7628         // normal case
7629         // result = left & right
7630         if(AOP_TYPE(right) == AOP_LIT){
7631           int t = (lit >> (offset*8)) & 0x0FFL;
7632           switch(t) { 
7633           case 0x00:
7634             pic16_emitcode("clrf","%s",
7635                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7636             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7637             break;
7638           case 0xff:
7639             pic16_emitcode("movf","%s,w",
7640                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7641             pic16_emitcode("movwf","%s",
7642                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7643             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7644             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7645             break;
7646           default:
7647             pic16_emitcode("movlw","0x%x",t);
7648             pic16_emitcode("andwf","%s,w",
7649                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7650             pic16_emitcode("movwf","%s",
7651                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7652               
7653             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7654             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7655             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7656           }
7657           continue;
7658         }
7659
7660         if (AOP_TYPE(left) == AOP_ACC) {
7661           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7662           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7663         } else {
7664           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7665           pic16_emitcode("andwf","%s,w",
7666                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7667           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7668           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7669         }
7670         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7671         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7672       }
7673     }
7674   }
7675
7676   release :
7677     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7678   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679   pic16_freeAsmop(result,NULL,ic,TRUE);     
7680 }
7681
7682 /*-----------------------------------------------------------------*/
7683 /* genOr  - code for or                                            */
7684 /*-----------------------------------------------------------------*/
7685 static void genOr (iCode *ic, iCode *ifx)
7686 {
7687     operand *left, *right, *result;
7688     int size, offset=0;
7689     unsigned long lit = 0L;
7690
7691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7692
7693     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7694     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7695     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7696
7697     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7698
7699     /* if left is a literal & right is not then exchange them */
7700     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7701         AOP_NEEDSACC(left)) {
7702         operand *tmp = right ;
7703         right = left;
7704         left = tmp;
7705     }
7706
7707     /* if result = right then exchange them */
7708     if(pic16_sameRegs(AOP(result),AOP(right))){
7709         operand *tmp = right ;
7710         right = left;
7711         left = tmp;
7712     }
7713
7714     /* if right is bit then exchange them */
7715     if (AOP_TYPE(right) == AOP_CRY &&
7716         AOP_TYPE(left) != AOP_CRY){
7717         operand *tmp = right ;
7718         right = left;
7719         left = tmp;
7720     }
7721
7722     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7723
7724     if(AOP_TYPE(right) == AOP_LIT)
7725         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7726
7727     size = AOP_SIZE(result);
7728
7729     // if(bit | yy)
7730     // xx = bit | yy;
7731     if (AOP_TYPE(left) == AOP_CRY){
7732         if(AOP_TYPE(right) == AOP_LIT){
7733             // c = bit & literal;
7734             if(lit){
7735                 // lit != 0 => result = 1
7736                 if(AOP_TYPE(result) == AOP_CRY){
7737                   if(size)
7738                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7739                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7740                   //     AOP(result)->aopu.aop_dir,
7741                   //     AOP(result)->aopu.aop_dir);
7742                     else if(ifx)
7743                         continueIfTrue(ifx);
7744                     goto release;
7745                 }
7746             } else {
7747                 // lit == 0 => result = left
7748                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7749                     goto release;
7750                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7751             }
7752         } else {
7753             if (AOP_TYPE(right) == AOP_CRY){
7754               if(pic16_sameRegs(AOP(result),AOP(left))){
7755                 // c = bit | bit;
7756                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7757                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7758                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7759
7760                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7761                          AOP(result)->aopu.aop_dir,
7762                          AOP(result)->aopu.aop_dir);
7763                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7764                          AOP(right)->aopu.aop_dir,
7765                          AOP(right)->aopu.aop_dir);
7766                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7767                          AOP(result)->aopu.aop_dir,
7768                          AOP(result)->aopu.aop_dir);
7769               } else {
7770                 if( AOP_TYPE(result) == AOP_ACC) {
7771                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7772                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7773                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7774                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7775
7776                 } else {
7777
7778                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7779                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7780                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7781                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7782
7783                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7784                                  AOP(result)->aopu.aop_dir,
7785                                  AOP(result)->aopu.aop_dir);
7786                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7787                                  AOP(right)->aopu.aop_dir,
7788                                  AOP(right)->aopu.aop_dir);
7789                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7790                                  AOP(left)->aopu.aop_dir,
7791                                  AOP(left)->aopu.aop_dir);
7792                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7793                                  AOP(result)->aopu.aop_dir,
7794                                  AOP(result)->aopu.aop_dir);
7795                 }
7796               }
7797             } else {
7798                 // c = bit | val;
7799                 symbol *tlbl = newiTempLabel(NULL);
7800                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7801
7802
7803                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7804                 if( AOP_TYPE(right) == AOP_ACC) {
7805                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7806                   emitSKPNZ;
7807                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7808                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7809                 }
7810
7811
7812
7813                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7814                     pic16_emitcode(";XXX setb","c");
7815                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7816                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7817                 pic16_toBoolean(right);
7818                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7819                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7820                     jmpTrueOrFalse(ifx, tlbl);
7821                     goto release;
7822                 } else {
7823                     CLRC;
7824                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7825                 }
7826             }
7827         }
7828         // bit = c
7829         // val = c
7830         if(size)
7831             pic16_outBitC(result);
7832         // if(bit | ...)
7833         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7834             genIfxJump(ifx, "c");           
7835         goto release ;
7836     }
7837
7838     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7839     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7840     if((AOP_TYPE(right) == AOP_LIT) &&
7841        (AOP_TYPE(result) == AOP_CRY) &&
7842        (AOP_TYPE(left) != AOP_CRY)){
7843         if(lit){
7844           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845             // result = 1
7846             if(size)
7847                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7848             else 
7849                 continueIfTrue(ifx);
7850             goto release;
7851         } else {
7852           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7853             // lit = 0, result = boolean(left)
7854             if(size)
7855                 pic16_emitcode(";XXX setb","c");
7856             pic16_toBoolean(right);
7857             if(size){
7858                 symbol *tlbl = newiTempLabel(NULL);
7859                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7860                 CLRC;
7861                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7862             } else {
7863                 genIfxJump (ifx,"a");
7864                 goto release;
7865             }
7866         }
7867         pic16_outBitC(result);
7868         goto release ;
7869     }
7870
7871     /* if left is same as result */
7872     if(pic16_sameRegs(AOP(result),AOP(left))){
7873       int know_W = -1;
7874       for(;size--; offset++,lit>>=8) {
7875         if(AOP_TYPE(right) == AOP_LIT){
7876           if((lit & 0xff) == 0)
7877             /*  or'ing with 0 has no effect */
7878             continue;
7879           else {
7880             int p = pic16_my_powof2(lit & 0xff);
7881             if(p>=0) {
7882               /* only one bit is set in the literal, so use a bsf instruction */
7883               pic16_emitpcode(POC_BSF,
7884                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7885             } else {
7886               if(know_W != (lit & 0xff))
7887                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7888               know_W = lit & 0xff;
7889               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7890             }
7891                     
7892           }
7893         } else {
7894           if (AOP_TYPE(left) == AOP_ACC) {
7895             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7896             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897           } else {                  
7898             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7899             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7900
7901             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7903
7904           }
7905         }
7906       }
7907     } else {
7908         // left & result in different registers
7909         if(AOP_TYPE(result) == AOP_CRY){
7910             // result = bit
7911             // if(size), result in bit
7912             // if(!size && ifx), conditional oper: if(left | right)
7913             symbol *tlbl = newiTempLabel(NULL);
7914             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7915             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7916
7917
7918             if(size)
7919                 pic16_emitcode(";XXX setb","c");
7920             while(sizer--){
7921                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7922                 pic16_emitcode(";XXX orl","a,%s",
7923                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7925                 offset++;
7926             }
7927             if(size){
7928                 CLRC;
7929                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7930                 pic16_outBitC(result);
7931             } else if(ifx)
7932                 jmpTrueOrFalse(ifx, tlbl);
7933         } else for(;(size--);offset++){
7934           // normal case
7935           // result = left & right
7936           if(AOP_TYPE(right) == AOP_LIT){
7937             int t = (lit >> (offset*8)) & 0x0FFL;
7938             switch(t) { 
7939             case 0x00:
7940               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7941               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7942
7943               pic16_emitcode("movf","%s,w",
7944                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7945               pic16_emitcode("movwf","%s",
7946                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7947               break;
7948             default:
7949               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7950               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7951               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7952
7953               pic16_emitcode("movlw","0x%x",t);
7954               pic16_emitcode("iorwf","%s,w",
7955                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7956               pic16_emitcode("movwf","%s",
7957                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7958               
7959             }
7960             continue;
7961           }
7962
7963           // faster than result <- left, anl result,right
7964           // and better if result is SFR
7965           if (AOP_TYPE(left) == AOP_ACC) {
7966             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7967             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7968           } else {
7969             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7970             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7971
7972             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7973             pic16_emitcode("iorwf","%s,w",
7974                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7975           }
7976           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7977           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7978         }
7979     }
7980
7981 release :
7982     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7983     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7984     pic16_freeAsmop(result,NULL,ic,TRUE);     
7985 }
7986
7987 /*-----------------------------------------------------------------*/
7988 /* genXor - code for xclusive or                                   */
7989 /*-----------------------------------------------------------------*/
7990 static void genXor (iCode *ic, iCode *ifx)
7991 {
7992   operand *left, *right, *result;
7993   int size, offset=0;
7994   unsigned long lit = 0L;
7995
7996   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7997
7998   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7999   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8000   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8001
8002   /* if left is a literal & right is not ||
8003      if left needs acc & right does not */
8004   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8005       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8006     operand *tmp = right ;
8007     right = left;
8008     left = tmp;
8009   }
8010
8011   /* if result = right then exchange them */
8012   if(pic16_sameRegs(AOP(result),AOP(right))){
8013     operand *tmp = right ;
8014     right = left;
8015     left = tmp;
8016   }
8017
8018   /* if right is bit then exchange them */
8019   if (AOP_TYPE(right) == AOP_CRY &&
8020       AOP_TYPE(left) != AOP_CRY){
8021     operand *tmp = right ;
8022     right = left;
8023     left = tmp;
8024   }
8025   if(AOP_TYPE(right) == AOP_LIT)
8026     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8027
8028   size = AOP_SIZE(result);
8029
8030   // if(bit ^ yy)
8031   // xx = bit ^ yy;
8032   if (AOP_TYPE(left) == AOP_CRY){
8033     if(AOP_TYPE(right) == AOP_LIT){
8034       // c = bit & literal;
8035       if(lit>>1){
8036         // lit>>1  != 0 => result = 1
8037         if(AOP_TYPE(result) == AOP_CRY){
8038           if(size)
8039             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8040             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8041           else if(ifx)
8042             continueIfTrue(ifx);
8043           goto release;
8044         }
8045         pic16_emitcode("setb","c");
8046       } else{
8047         // lit == (0 or 1)
8048         if(lit == 0){
8049           // lit == 0, result = left
8050           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8051             goto release;
8052           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8053         } else{
8054           // lit == 1, result = not(left)
8055           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8056             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8057             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8058             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8059             goto release;
8060           } else {
8061             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8062             pic16_emitcode("cpl","c");
8063           }
8064         }
8065       }
8066
8067     } else {
8068       // right != literal
8069       symbol *tlbl = newiTempLabel(NULL);
8070       if (AOP_TYPE(right) == AOP_CRY){
8071         // c = bit ^ bit;
8072         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8073       }
8074       else{
8075         int sizer = AOP_SIZE(right);
8076         // c = bit ^ val
8077         // if val>>1 != 0, result = 1
8078         pic16_emitcode("setb","c");
8079         while(sizer){
8080           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8081           if(sizer == 1)
8082             // test the msb of the lsb
8083             pic16_emitcode("anl","a,#0xfe");
8084           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8085           sizer--;
8086         }
8087         // val = (0,1)
8088         pic16_emitcode("rrc","a");
8089       }
8090       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8091       pic16_emitcode("cpl","c");
8092       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8093     }
8094     // bit = c
8095     // val = c
8096     if(size)
8097       pic16_outBitC(result);
8098     // if(bit | ...)
8099     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8100       genIfxJump(ifx, "c");           
8101     goto release ;
8102   }
8103
8104   if(pic16_sameRegs(AOP(result),AOP(left))){
8105     /* if left is same as result */
8106     for(;size--; offset++) {
8107       if(AOP_TYPE(right) == AOP_LIT){
8108         int t  = (lit >> (offset*8)) & 0x0FFL;
8109         if(t == 0x00L)
8110           continue;
8111         else
8112           if (IS_AOP_PREG(left)) {
8113             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8115             pic16_aopPut(AOP(result),"a",offset);
8116           } else {
8117             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8118             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8119             pic16_emitcode("xrl","%s,%s",
8120                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8121                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122           }
8123       } else {
8124         if (AOP_TYPE(left) == AOP_ACC)
8125           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126         else {
8127           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8128           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8129 /*
8130           if (IS_AOP_PREG(left)) {
8131             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132             pic16_aopPut(AOP(result),"a",offset);
8133           } else
8134             pic16_emitcode("xrl","%s,a",
8135                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136 */
8137         }
8138       }
8139     }
8140   } else {
8141     // left & result in different registers
8142     if(AOP_TYPE(result) == AOP_CRY){
8143       // result = bit
8144       // if(size), result in bit
8145       // if(!size && ifx), conditional oper: if(left ^ right)
8146       symbol *tlbl = newiTempLabel(NULL);
8147       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8148       if(size)
8149         pic16_emitcode("setb","c");
8150       while(sizer--){
8151         if((AOP_TYPE(right) == AOP_LIT) &&
8152            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8153           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8154         } else {
8155           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8156           pic16_emitcode("xrl","a,%s",
8157                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158         }
8159         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8160         offset++;
8161       }
8162       if(size){
8163         CLRC;
8164         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8165         pic16_outBitC(result);
8166       } else if(ifx)
8167         jmpTrueOrFalse(ifx, tlbl);
8168     } else for(;(size--);offset++){
8169       // normal case
8170       // result = left & right
8171       if(AOP_TYPE(right) == AOP_LIT){
8172         int t = (lit >> (offset*8)) & 0x0FFL;
8173         switch(t) { 
8174         case 0x00:
8175           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8176           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177           pic16_emitcode("movf","%s,w",
8178                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179           pic16_emitcode("movwf","%s",
8180                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181           break;
8182         case 0xff:
8183           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8184           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8185           pic16_emitcode("comf","%s,w",
8186                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8187           pic16_emitcode("movwf","%s",
8188                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8189           break;
8190         default:
8191           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8192           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8193           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8194           pic16_emitcode("movlw","0x%x",t);
8195           pic16_emitcode("xorwf","%s,w",
8196                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8197           pic16_emitcode("movwf","%s",
8198                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8199
8200         }
8201         continue;
8202       }
8203
8204       // faster than result <- left, anl result,right
8205       // and better if result is SFR
8206       if (AOP_TYPE(left) == AOP_ACC) {
8207         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8208         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8209       } else {
8210         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8211         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8212         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8214       }
8215       if ( AOP_TYPE(result) != AOP_ACC){
8216         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8217         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8218       }
8219     }
8220   }
8221
8222   release :
8223     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8224   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8225   pic16_freeAsmop(result,NULL,ic,TRUE);     
8226 }
8227
8228 /*-----------------------------------------------------------------*/
8229 /* genInline - write the inline code out                           */
8230 /*-----------------------------------------------------------------*/
8231 static void genInline (iCode *ic)
8232 {
8233   char *buffer, *bp, *bp1;
8234   char *cbuf;
8235     
8236         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8237
8238         _G.inLine += (!options.asmpeep);
8239
8240         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8241         strcpy(buffer,IC_INLINE(ic));
8242         
8243         while((bp1=strstr(bp, "\\n"))) {
8244           *bp1++ = '\n';
8245           *bp1++ = ' ';
8246           bp = bp1;
8247         }
8248         bp = bp1 = buffer;
8249
8250         cbuf = Safe_strdup( buffer );
8251
8252         if(asmInlineMap)
8253         {
8254           symbol *sym;
8255           char *s;
8256           int cblen;
8257
8258             cbuf = Safe_strdup(buffer);
8259             cblen = strlen(buffer)+1;
8260             memset(cbuf, 0, cblen);
8261
8262             bp = buffer;
8263             bp1 = cbuf;
8264             while(*bp) {
8265               if(*bp != '%')*bp1++ = *bp++;
8266               else {
8267                 int i;
8268
8269                   bp++;
8270                   i = *bp - '0';
8271                   if(i>elementsInSet(asmInlineMap))break;
8272                   
8273                   bp++;
8274                   s = indexSet(asmInlineMap, i);
8275                   DEBUGpc("searching symbol s = `%s'", s);
8276                   sym = findSym(SymbolTab, NULL, s);
8277
8278                   if(sym->reqv) {
8279                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8280                   } else {
8281                     strcat(bp1, sym->rname);
8282                   }
8283                   
8284                   while(*bp1)bp1++;
8285               }
8286               
8287               if(strlen(bp1) > cblen - 16) {
8288                 int i = strlen(cbuf);
8289                 cblen += 50;
8290                 cbuf = realloc(cbuf, cblen);
8291                 memset(cbuf+i, 0, 50);
8292                 bp1 = cbuf + i;
8293               }
8294             }
8295             
8296             free(buffer);
8297             buffer = Safe_strdup( cbuf );
8298             free(cbuf);
8299             
8300             bp = bp1 = buffer;
8301         }
8302
8303         /* emit each line as a code */
8304         while (*bp) {
8305                 if (*bp == '\n') {
8306                         *bp++ = '\0';
8307
8308                         if(*bp1)
8309                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8310                         bp1 = bp;
8311                 } else {
8312                         if (*bp == ':') {
8313                                 bp++;
8314                                 *bp = '\0';
8315                                 bp++;
8316
8317                                 /* print label, use this special format with NULL directive
8318                                  * to denote that the argument should not be indented with tab */
8319                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8320                                 bp1 = bp;
8321                         } else
8322                                 bp++;
8323                 }
8324         }
8325
8326         if ((bp1 != bp) && *bp1)
8327                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8328
8329
8330     Safe_free(buffer);
8331
8332     _G.inLine -= (!options.asmpeep);
8333 }
8334
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry                                */
8337 /*-----------------------------------------------------------------*/
8338 static void genRRC (iCode *ic)
8339 {
8340   operand *left , *result ;
8341   int size, offset = 0, same;
8342
8343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8344
8345   /* rotate right with carry */
8346   left = IC_LEFT(ic);
8347   result=IC_RESULT(ic);
8348   pic16_aopOp (left,ic,FALSE);
8349   pic16_aopOp (result,ic,TRUE);
8350
8351   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8352
8353   same = pic16_sameRegs(AOP(result),AOP(left));
8354
8355   size = AOP_SIZE(result);    
8356
8357   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8358
8359   /* get the lsb and put it into the carry */
8360   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8361
8362   offset = 0 ;
8363
8364   while(size--) {
8365
8366     if(same) {
8367       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8368     } else {
8369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8370       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8371     }
8372
8373     offset++;
8374   }
8375
8376   pic16_freeAsmop(left,NULL,ic,TRUE);
8377   pic16_freeAsmop(result,NULL,ic,TRUE);
8378 }
8379
8380 /*-----------------------------------------------------------------*/
8381 /* genRLC - generate code for rotate left with carry               */
8382 /*-----------------------------------------------------------------*/
8383 static void genRLC (iCode *ic)
8384 {    
8385   operand *left , *result ;
8386   int size, offset = 0;
8387   int same;
8388
8389   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8390   /* rotate right with carry */
8391   left = IC_LEFT(ic);
8392   result=IC_RESULT(ic);
8393   pic16_aopOp (left,ic,FALSE);
8394   pic16_aopOp (result,ic,TRUE);
8395
8396   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8397
8398   same = pic16_sameRegs(AOP(result),AOP(left));
8399
8400   /* move it to the result */
8401   size = AOP_SIZE(result);    
8402
8403   /* get the msb and put it into the carry */
8404   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8405
8406   offset = 0 ;
8407
8408   while(size--) {
8409
8410     if(same) {
8411       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8412     } else {
8413       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8414       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8415     }
8416
8417     offset++;
8418   }
8419
8420
8421   pic16_freeAsmop(left,NULL,ic,TRUE);
8422   pic16_freeAsmop(result,NULL,ic,TRUE);
8423 }
8424
8425
8426 /* gpasm can get the highest order bit with HIGH/UPPER
8427  * so the following probably is not needed -- VR */
8428  
8429 /*-----------------------------------------------------------------*/
8430 /* genGetHbit - generates code get highest order bit               */
8431 /*-----------------------------------------------------------------*/
8432 static void genGetHbit (iCode *ic)
8433 {
8434     operand *left, *result;
8435     left = IC_LEFT(ic);
8436     result=IC_RESULT(ic);
8437     pic16_aopOp (left,ic,FALSE);
8438     pic16_aopOp (result,ic,FALSE);
8439
8440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441     /* get the highest order byte into a */
8442     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8443     if(AOP_TYPE(result) == AOP_CRY){
8444         pic16_emitcode("rlc","a");
8445         pic16_outBitC(result);
8446     }
8447     else{
8448         pic16_emitcode("rl","a");
8449         pic16_emitcode("anl","a,#0x01");
8450         pic16_outAcc(result);
8451     }
8452
8453
8454     pic16_freeAsmop(left,NULL,ic,TRUE);
8455     pic16_freeAsmop(result,NULL,ic,TRUE);
8456 }
8457
8458 #if 0
8459 /*-----------------------------------------------------------------*/
8460 /* AccRol - rotate left accumulator by known count                 */
8461 /*-----------------------------------------------------------------*/
8462 static void AccRol (int shCount)
8463 {
8464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8465     shCount &= 0x0007;              // shCount : 0..7
8466     switch(shCount){
8467         case 0 :
8468             break;
8469         case 1 :
8470             pic16_emitcode("rl","a");
8471             break;
8472         case 2 :
8473             pic16_emitcode("rl","a");
8474             pic16_emitcode("rl","a");
8475             break;
8476         case 3 :
8477             pic16_emitcode("swap","a");
8478             pic16_emitcode("rr","a");
8479             break;
8480         case 4 :
8481             pic16_emitcode("swap","a");
8482             break;
8483         case 5 :
8484             pic16_emitcode("swap","a");
8485             pic16_emitcode("rl","a");
8486             break;
8487         case 6 :
8488             pic16_emitcode("rr","a");
8489             pic16_emitcode("rr","a");
8490             break;
8491         case 7 :
8492             pic16_emitcode("rr","a");
8493             break;
8494     }
8495 }
8496 #endif
8497
8498 /*-----------------------------------------------------------------*/
8499 /* AccLsh - left shift accumulator by known count                  */
8500 /*-----------------------------------------------------------------*/
8501 static void AccLsh (int shCount)
8502 {
8503         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8504         switch(shCount){
8505                 case 0 :
8506                         return;
8507                         break;
8508                 case 1 :
8509                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510                         break;
8511                 case 2 :
8512                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514                         break;
8515                 case 3 :
8516                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518                         break;
8519                 case 4 :
8520                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 5 :
8523                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 6 :
8527                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 7 :
8531                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533         }
8534
8535         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8536 }
8537
8538 /*-----------------------------------------------------------------*/
8539 /* AccRsh - right shift accumulator by known count                 */
8540 /*-----------------------------------------------------------------*/
8541 static void AccRsh (int shCount, int andmask)
8542 {
8543         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8544         switch(shCount){
8545                 case 0 :
8546                         return; break;
8547                 case 1 :
8548                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         break;
8550                 case 2 :
8551                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         break;
8554                 case 3 :
8555                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         break;
8558                 case 4 :
8559                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         break;
8561                 case 5 :
8562                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         break;
8565                 case 6 :
8566                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569                 case 7 :
8570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571                         break;
8572         }
8573         
8574         if(andmask)
8575                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8576         else
8577                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8578 }
8579
8580 #if 0
8581 /*-----------------------------------------------------------------*/
8582 /* AccSRsh - signed right shift accumulator by known count                 */
8583 /*-----------------------------------------------------------------*/
8584 static void AccSRsh (int shCount)
8585 {
8586     symbol *tlbl ;
8587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8588     if(shCount != 0){
8589         if(shCount == 1){
8590             pic16_emitcode("mov","c,acc.7");
8591             pic16_emitcode("rrc","a");
8592         } else if(shCount == 2){
8593             pic16_emitcode("mov","c,acc.7");
8594             pic16_emitcode("rrc","a");
8595             pic16_emitcode("mov","c,acc.7");
8596             pic16_emitcode("rrc","a");
8597         } else {
8598             tlbl = newiTempLabel(NULL);
8599             /* rotate right accumulator */
8600             AccRol(8 - shCount);
8601             /* and kill the higher order bits */
8602             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8603             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8604             pic16_emitcode("orl","a,#0x%02x",
8605                      (unsigned char)~SRMask[shCount]);
8606             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8607         }
8608     }
8609 }
8610 #endif
8611
8612 /*-----------------------------------------------------------------*/
8613 /* shiftR1Left2Result - shift right one byte from left to result   */
8614 /*-----------------------------------------------------------------*/
8615 static void shiftR1Left2ResultSigned (operand *left, int offl,
8616                                 operand *result, int offr,
8617                                 int shCount)
8618 {
8619   int same;
8620
8621   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8622
8623   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8624
8625   switch(shCount) {
8626   case 1:
8627     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8628     if(same) 
8629       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8630     else {
8631       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8632       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8633     }
8634
8635     break;
8636   case 2:
8637
8638     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8639     if(same) 
8640       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8641     else {
8642       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8644     }
8645     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8646     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8647
8648     break;
8649
8650   case 3:
8651     if(same)
8652       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8653     else {
8654       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8655       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8656     }
8657
8658     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8659     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8660     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8661
8662     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8663     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8664
8665     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8666     break;
8667
8668   case 4:
8669     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8670     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8671     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8672     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8673     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8674     break;
8675   case 5:
8676     if(same) {
8677       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8678     } else {
8679       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8680       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8681     }
8682     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8687     break;
8688
8689   case 6:
8690     if(same) {
8691       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8692       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8693       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8694       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8695       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8696       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697     } else {
8698       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8699       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8700       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8701       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8702       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8703     }
8704     break;
8705
8706   case 7:
8707     if(same) {
8708       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8709       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8710       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712     } else {
8713       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8714       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8716     }
8717
8718   default:
8719     break;
8720   }
8721 }
8722
8723 /*-----------------------------------------------------------------*/
8724 /* shiftR1Left2Result - shift right one byte from left to result   */
8725 /*-----------------------------------------------------------------*/
8726 static void shiftR1Left2Result (operand *left, int offl,
8727                                 operand *result, int offr,
8728                                 int shCount, int sign)
8729 {
8730   int same;
8731
8732   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8733
8734   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8735
8736   /* Copy the msb into the carry if signed. */
8737   if(sign) {
8738     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8739     return;
8740   }
8741
8742
8743
8744   switch(shCount) {
8745   case 1:
8746     emitCLRC;
8747     if(same) 
8748       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8749     else {
8750       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8752     }
8753     break;
8754   case 2:
8755     emitCLRC;
8756     if(same) {
8757       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8758     } else {
8759       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761     }
8762     emitCLRC;
8763     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8764
8765     break;
8766   case 3:
8767     if(same)
8768       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8769     else {
8770       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8771       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772     }
8773
8774     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8775     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8776     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8777     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778     break;
8779       
8780   case 4:
8781     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8783     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8784     break;
8785
8786   case 5:
8787     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8788     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8789     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790     //emitCLRC;
8791     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8792
8793     break;
8794   case 6:
8795
8796     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8797     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8798     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8800     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8801     break;
8802
8803   case 7:
8804
8805     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8806     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8807     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8808
8809     break;
8810
8811   default:
8812     break;
8813   }
8814 }
8815
8816 /*-----------------------------------------------------------------*/
8817 /* shiftL1Left2Result - shift left one byte from left to result    */
8818 /*-----------------------------------------------------------------*/
8819 static void shiftL1Left2Result (operand *left, int offl,
8820                                 operand *result, int offr, int shCount)
8821 {
8822   int same;
8823
8824   //    char *l;
8825   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8826
8827   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8828   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8829     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8830     //    MOVA(l);
8831     /* shift left accumulator */
8832     //AccLsh(shCount); // don't comment out just yet...
8833   //    pic16_aopPut(AOP(result),"a",offr);
8834
8835   switch(shCount) {
8836   case 1:
8837     /* Shift left 1 bit position */
8838     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8839     if(same) {
8840       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8841     } else {
8842       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8843       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8844     }
8845     break;
8846   case 2:
8847     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8849     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8851     break;
8852   case 3:
8853     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8854     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8855     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8858     break;
8859   case 4:
8860     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8861     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863     break;
8864   case 5:
8865     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8867     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8869     break;
8870   case 6:
8871     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8873     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8876     break;
8877   case 7:
8878     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8879     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8880     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8881     break;
8882
8883   default:
8884     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8885   }
8886
8887 }
8888
8889 /*-----------------------------------------------------------------*/
8890 /* movLeft2Result - move byte from left to result                  */
8891 /*-----------------------------------------------------------------*/
8892 static void movLeft2Result (operand *left, int offl,
8893                             operand *result, int offr)
8894 {
8895   char *l;
8896   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8897   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8898     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8899
8900     if (*l == '@' && (IS_AOP_PREG(result))) {
8901       pic16_emitcode("mov","a,%s",l);
8902       pic16_aopPut(AOP(result),"a",offr);
8903     } else {
8904       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906     }
8907   }
8908 }
8909
8910 /*-----------------------------------------------------------------*/
8911 /* shiftL2Left2Result - shift left two bytes from left to result   */
8912 /*-----------------------------------------------------------------*/
8913 static void shiftL2Left2Result (operand *left, int offl,
8914                                 operand *result, int offr, int shCount)
8915 {
8916   int same = pic16_sameRegs(AOP(result), AOP(left));
8917   int i;
8918
8919   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8920
8921   if (same && (offl != offr)) { // shift bytes
8922     if (offr > offl) {
8923        for(i=1;i>-1;i--) {
8924          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8925          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8926        }
8927     } else { // just treat as different later on
8928                 same = 0;
8929     }
8930   }
8931
8932   if(same) {
8933     switch(shCount) {
8934     case 0:
8935       break;
8936     case 1:
8937     case 2:
8938     case 3:
8939
8940       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8941       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8942       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8943
8944       while(--shCount) {
8945                 emitCLRC;
8946                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8947                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8948       }
8949
8950       break;
8951     case 4:
8952     case 5:
8953       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8954       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8955       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8956       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8957       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8958       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8959       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8960       if(shCount >=5) {
8961                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8962                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8963       }
8964       break;
8965     case 6:
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8967       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976       break;
8977     case 7:
8978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8979       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8980       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983     }
8984
8985   } else {
8986     switch(shCount) {
8987     case 0:
8988       break;
8989     case 1:
8990     case 2:
8991     case 3:
8992       /* note, use a mov/add for the shift since the mov has a
8993          chance of getting optimized out */
8994       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8995       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8996       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8997       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8998       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8999
9000       while(--shCount) {
9001                 emitCLRC;
9002                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9003                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9004       }
9005       break;
9006
9007     case 4:
9008     case 5:
9009       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9010       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9013       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9015       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9016       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9017
9018
9019       if(shCount == 5) {
9020                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9021                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9022       }
9023       break;
9024     case 6:
9025       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9026       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9028       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9029
9030       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9033       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9034       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9037       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9038       break;
9039     case 7:
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9041       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9042       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9043       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9045     }
9046   }
9047
9048 }
9049 /*-----------------------------------------------------------------*/
9050 /* shiftR2Left2Result - shift right two bytes from left to result  */
9051 /*-----------------------------------------------------------------*/
9052 static void shiftR2Left2Result (operand *left, int offl,
9053                                 operand *result, int offr,
9054                                 int shCount, int sign)
9055 {
9056   int same = pic16_sameRegs(AOP(result), AOP(left));
9057   int i;
9058   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9059
9060   if (same && (offl != offr)) { // shift right bytes
9061     if (offr < offl) {
9062        for(i=0;i<2;i++) {
9063          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9064          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9065        }
9066     } else { // just treat as different later on
9067                 same = 0;
9068     }
9069   }
9070
9071   switch(shCount) {
9072   case 0:
9073     break;
9074   case 1:
9075   case 2:
9076   case 3:
9077     if(sign)
9078       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9079     else
9080       emitCLRC;
9081
9082     if(same) {
9083       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9084       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9085     } else {
9086       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9087       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9088       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9089       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9090     }
9091
9092     while(--shCount) {
9093       if(sign)
9094                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9095       else
9096                 emitCLRC;
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9099     }
9100     break;
9101   case 4:
9102   case 5:
9103     if(same) {
9104
9105       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9106       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9107       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9108
9109       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9110       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9112       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9113     } else {
9114       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9115       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9116       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9117
9118       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9119       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9120       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9122       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9123     }
9124
9125     if(shCount >=5) {
9126       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9127       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9128     }
9129
9130     if(sign) {
9131       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9132       pic16_emitpcode(POC_BTFSC, 
9133                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9134       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9135     }
9136
9137     break;
9138
9139   case 6:
9140     if(same) {
9141
9142       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9143       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9144
9145       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9146       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9147       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9148       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9149       if(sign) {
9150         pic16_emitpcode(POC_BTFSC, 
9151                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9152         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9153       }
9154       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9157       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9158     } else {
9159       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9160       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9162       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9164       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9165       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9166       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9167       if(sign) {
9168         pic16_emitpcode(POC_BTFSC, 
9169                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9170         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9171       }
9172       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9173       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9174
9175         
9176     }
9177
9178     break;
9179   case 7:
9180     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9181     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9182     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9183     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9184     if(sign) {
9185       emitSKPNC;
9186       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9187     } else 
9188       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9189   }
9190 }
9191
9192
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9195 /*-----------------------------------------------------------------*/
9196 static void shiftLLeftOrResult (operand *left, int offl,
9197                                 operand *result, int offr, int shCount)
9198 {
9199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9200
9201     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9202     /* shift left accumulator */
9203     AccLsh(shCount);
9204     /* or with result */
9205     /* back to result */
9206     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9207 }
9208
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9211 /*-----------------------------------------------------------------*/
9212 static void shiftRLeftOrResult (operand *left, int offl,
9213                                 operand *result, int offr, int shCount)
9214 {
9215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9216     
9217     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9218     /* shift right accumulator */
9219     AccRsh(shCount, 1);
9220     /* or with result */
9221     /* back to result */
9222     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genlshOne - left shift a one byte quantity by known count       */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshOne (operand *result, operand *left, int shCount)
9229 {       
9230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9231     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9232 }
9233
9234 /*-----------------------------------------------------------------*/
9235 /* genlshTwo - left shift two bytes by known amount != 0           */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshTwo (operand *result,operand *left, int shCount)
9238 {
9239     int size;
9240     
9241     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9242     size = pic16_getDataSize(result);
9243
9244     /* if shCount >= 8 */
9245     if (shCount >= 8) {
9246         shCount -= 8 ;
9247
9248         if (size > 1){
9249             if (shCount)
9250                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9251             else 
9252                 movLeft2Result(left, LSB, result, MSB16);
9253         }
9254         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9255     }
9256
9257     /*  1 <= shCount <= 7 */
9258     else {  
9259         if(size == 1)
9260             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9261         else 
9262             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9263     }
9264 }
9265
9266 /*-----------------------------------------------------------------*/
9267 /* shiftLLong - shift left one long from left to result            */
9268 /* offr = LSB or MSB16                                             */
9269 /*-----------------------------------------------------------------*/
9270 static void shiftLLong (operand *left, operand *result, int offr )
9271 {
9272     int size = AOP_SIZE(result);
9273     int same = pic16_sameRegs(AOP(left),AOP(result));
9274         int i;
9275
9276     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9277
9278         if (same && (offr == MSB16)) { //shift one byte
9279                 for(i=size-1;i>=MSB16;i--) {
9280                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9281                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9282                 }
9283         } else {
9284                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9285         }
9286         
9287     if (size > LSB+offr ){
9288                 if (same) {
9289                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9290                 } else {
9291                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9292                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9293                 }
9294          }
9295
9296     if(size > MSB16+offr){
9297                 if (same) {
9298                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9299                 } else {
9300                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9301                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9302                 }
9303     }
9304
9305     if(size > MSB24+offr){
9306                 if (same) {
9307                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9308                 } else {
9309                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9310                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9311                 }
9312     }
9313
9314     if(size > MSB32+offr){
9315                 if (same) {
9316                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9317                 } else {
9318                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9319                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9320                 }
9321     }
9322     if(offr != LSB)
9323                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9324
9325 }
9326
9327 /*-----------------------------------------------------------------*/
9328 /* genlshFour - shift four byte by a known amount != 0             */
9329 /*-----------------------------------------------------------------*/
9330 static void genlshFour (operand *result, operand *left, int shCount)
9331 {
9332     int size;
9333
9334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9335     size = AOP_SIZE(result);
9336
9337     /* if shifting more that 3 bytes */
9338     if (shCount >= 24 ) {
9339         shCount -= 24;
9340         if (shCount)
9341             /* lowest order of left goes to the highest
9342             order of the destination */
9343             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9344         else
9345             movLeft2Result(left, LSB, result, MSB32);
9346
9347                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9348                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9349                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9350
9351         return;
9352     }
9353
9354     /* more than two bytes */
9355     else if ( shCount >= 16 ) {
9356         /* lower order two bytes goes to higher order two bytes */
9357         shCount -= 16;
9358         /* if some more remaining */
9359         if (shCount)
9360             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9361         else {
9362             movLeft2Result(left, MSB16, result, MSB32);
9363             movLeft2Result(left, LSB, result, MSB24);
9364         }
9365                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9366                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9367         return;
9368     }    
9369
9370     /* if more than 1 byte */
9371     else if ( shCount >= 8 ) {
9372         /* lower order three bytes goes to higher order  three bytes */
9373         shCount -= 8;
9374         if(size == 2){
9375             if(shCount)
9376                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9377             else
9378                 movLeft2Result(left, LSB, result, MSB16);
9379         }
9380         else{   /* size = 4 */
9381             if(shCount == 0){
9382                 movLeft2Result(left, MSB24, result, MSB32);
9383                 movLeft2Result(left, MSB16, result, MSB24);
9384                 movLeft2Result(left, LSB, result, MSB16);
9385                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9386             }
9387             else if(shCount == 1)
9388                 shiftLLong(left, result, MSB16);
9389             else{
9390                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9391                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9393                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9394             }
9395         }
9396     }
9397
9398     /* 1 <= shCount <= 7 */
9399     else if(shCount <= 3)
9400     { 
9401         shiftLLong(left, result, LSB);
9402         while(--shCount >= 1)
9403             shiftLLong(result, result, LSB);
9404     }
9405     /* 3 <= shCount <= 7, optimize */
9406     else{
9407         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9408         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9409         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9410     }
9411 }
9412
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShiftLiteral - left shifting by known count              */
9415 /*-----------------------------------------------------------------*/
9416 void pic16_genLeftShiftLiteral (operand *left,
9417                                  operand *right,
9418                                  operand *result,
9419                                  iCode *ic)
9420 {    
9421     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9422     int size;
9423
9424     FENTRY;
9425     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9426     pic16_freeAsmop(right,NULL,ic,TRUE);
9427
9428     pic16_aopOp(left,ic,FALSE);
9429     pic16_aopOp(result,ic,TRUE);
9430
9431     size = getSize(operandType(result));
9432
9433 #if VIEW_SIZE
9434     pic16_emitcode("; shift left ","result %d, left %d",size,
9435              AOP_SIZE(left));
9436 #endif
9437
9438     /* I suppose that the left size >= result size */
9439     if(shCount == 0){
9440         while(size--){
9441             movLeft2Result(left, size, result, size);
9442         }
9443     }
9444
9445     else if(shCount >= (size * 8))
9446         while(size--)
9447             pic16_aopPut(AOP(result),zero,size);
9448     else{
9449         switch (size) {
9450             case 1:
9451                 genlshOne (result,left,shCount);
9452                 break;
9453
9454             case 2:
9455             case 3:
9456                 genlshTwo (result,left,shCount);
9457                 break;
9458
9459             case 4:
9460                 genlshFour (result,left,shCount);
9461                 break;
9462         }
9463     }
9464     pic16_freeAsmop(left,NULL,ic,TRUE);
9465     pic16_freeAsmop(result,NULL,ic,TRUE);
9466 }
9467
9468 /*-----------------------------------------------------------------*
9469  * genMultiAsm - repeat assembly instruction for size of register.
9470  * if endian == 1, then the high byte (i.e base address + size of 
9471  * register) is used first else the low byte is used first;
9472  *-----------------------------------------------------------------*/
9473 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9474 {
9475
9476   int offset = 0;
9477
9478   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9479
9480   if(!reg)
9481     return;
9482
9483   if(!endian) {
9484     endian = 1;
9485   } else {
9486     endian = -1;
9487     offset = size-1;
9488   }
9489
9490   while(size--) {
9491     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9492     offset += endian;
9493   }
9494
9495 }
9496
9497 #if !(USE_GENERIC_SIGNED_SHIFT)
9498 /*-----------------------------------------------------------------*/
9499 /* genLeftShift - generates code for left shifting                 */
9500 /*-----------------------------------------------------------------*/
9501 static void genLeftShift (iCode *ic)
9502 {
9503   operand *left,*right, *result;
9504   int size, offset;
9505 //  char *l;
9506   symbol *tlbl , *tlbl1;
9507   pCodeOp *pctemp;
9508
9509   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9510
9511   right = IC_RIGHT(ic);
9512   left  = IC_LEFT(ic);
9513   result = IC_RESULT(ic);
9514
9515   pic16_aopOp(right,ic,FALSE);
9516
9517   /* if the shift count is known then do it 
9518      as efficiently as possible */
9519   if (AOP_TYPE(right) == AOP_LIT) {
9520     pic16_genLeftShiftLiteral (left,right,result,ic);
9521     return ;
9522   }
9523
9524   /* shift count is unknown then we have to form
9525    * a loop. Get the loop count in WREG : Note: we take
9526    * only the lower order byte since shifting
9527    * more than 32 bits make no sense anyway, ( the
9528    * largest size of an object can be only 32 bits ) */
9529   
9530   pic16_aopOp(left,ic,FALSE);
9531   pic16_aopOp(result,ic,FALSE);
9532
9533   /* now move the left to the result if they are not the
9534    * same, and if size > 1,
9535    * and if right is not same to result (!!!) -- VR */
9536   if (!pic16_sameRegs(AOP(left),AOP(result))
9537       && (AOP_SIZE(result) > 1)) {
9538
9539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540
9541     size = AOP_SIZE(result);
9542     offset=0;
9543     while (size--) {
9544
9545 #if 0
9546       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9547       if (*l == '@' && (IS_AOP_PREG(result))) {
9548
9549           pic16_emitcode("mov","a,%s",l);
9550           pic16_aopPut(AOP(result),"a",offset);
9551       } else
9552 #endif
9553       {
9554         /* we don't know if left is a literal or a register, take care -- VR */
9555         mov2f(AOP(result), AOP(left), offset);
9556       }
9557       offset++;
9558     }
9559   }
9560
9561   size = AOP_SIZE(result);
9562
9563   /* if it is only one byte then */
9564   if (size == 1) {
9565     if(optimized_for_speed) {
9566       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9567       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9568       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9569       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9570       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9571       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9572       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9573       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9574       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9575       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9576       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9577       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9578     } else {
9579
9580       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9581
9582       tlbl = newiTempLabel(NULL);
9583
9584 #if 1
9585       /* this is already done, why change it? */
9586       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9587                 mov2f(AOP(result), AOP(left), 0);
9588       }
9589 #endif
9590
9591       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9592       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9593       pic16_emitpLabel(tlbl->key);
9594       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9595       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9596       emitSKPC;
9597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9598     }
9599     goto release ;
9600   }
9601     
9602   if (pic16_sameRegs(AOP(left),AOP(result))) {
9603
9604     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9605     
9606     tlbl = newiTempLabel(NULL);
9607     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9608     genMultiAsm(POC_RRCF, result, size,1);
9609     pic16_emitpLabel(tlbl->key);
9610     genMultiAsm(POC_RLCF, result, size,0);
9611     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9612     emitSKPC;
9613     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9614     goto release;
9615   }
9616
9617   //tlbl = newiTempLabel(NULL);
9618   //offset = 0 ;   
9619   //tlbl1 = newiTempLabel(NULL);
9620
9621   //reAdjustPreg(AOP(result));    
9622     
9623   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9624   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9625   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9626   //MOVA(l);
9627   //pic16_emitcode("add","a,acc");         
9628   //pic16_aopPut(AOP(result),"a",offset++);
9629   //while (--size) {
9630   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9631   //  MOVA(l);
9632   //  pic16_emitcode("rlc","a");         
9633   //  pic16_aopPut(AOP(result),"a",offset++);
9634   //}
9635   //reAdjustPreg(AOP(result));
9636
9637   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9638   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9639
9640
9641   tlbl = newiTempLabel(NULL);
9642   tlbl1= newiTempLabel(NULL);
9643
9644   size = AOP_SIZE(result);
9645   offset = 1;
9646
9647   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9648
9649   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9650
9651   /* offset should be 0, 1 or 3 */
9652   
9653   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9654   emitSKPNZ;
9655   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9656
9657   pic16_emitpcode(POC_MOVWF, pctemp);
9658
9659
9660   pic16_emitpLabel(tlbl->key);
9661
9662   emitCLRC;
9663   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9664   while(--size)
9665     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9666
9667   pic16_emitpcode(POC_DECFSZ,  pctemp);
9668   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9669   pic16_emitpLabel(tlbl1->key);
9670
9671   pic16_popReleaseTempReg(pctemp,1);
9672
9673
9674  release:
9675   pic16_freeAsmop (right,NULL,ic,TRUE);
9676   pic16_freeAsmop(left,NULL,ic,TRUE);
9677   pic16_freeAsmop(result,NULL,ic,TRUE);
9678 }
9679 #endif
9680
9681
9682 #if 0
9683 #error old code (left here for reference)
9684 /*-----------------------------------------------------------------*/
9685 /* genLeftShift - generates code for left shifting                 */
9686 /*-----------------------------------------------------------------*/
9687 static void genLeftShift (iCode *ic)
9688 {
9689   operand *left,*right, *result;
9690   int size, offset;
9691   char *l;
9692   symbol *tlbl , *tlbl1;
9693   pCodeOp *pctemp;
9694
9695   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9696
9697   right = IC_RIGHT(ic);
9698   left  = IC_LEFT(ic);
9699   result = IC_RESULT(ic);
9700
9701   pic16_aopOp(right,ic,FALSE);
9702
9703   /* if the shift count is known then do it 
9704      as efficiently as possible */
9705   if (AOP_TYPE(right) == AOP_LIT) {
9706     pic16_genLeftShiftLiteral (left,right,result,ic);
9707     return ;
9708   }
9709
9710   /* shift count is unknown then we have to form 
9711      a loop get the loop count in B : Note: we take
9712      only the lower order byte since shifting
9713      more that 32 bits make no sense anyway, ( the
9714      largest size of an object can be only 32 bits ) */  
9715
9716     
9717   pic16_aopOp(left,ic,FALSE);
9718   pic16_aopOp(result,ic,FALSE);
9719
9720   /* now move the left to the result if they are not the
9721      same */
9722   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9723       AOP_SIZE(result) > 1) {
9724
9725     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9726
9727     size = AOP_SIZE(result);
9728     offset=0;
9729     while (size--) {
9730       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9731       if (*l == '@' && (IS_AOP_PREG(result))) {
9732
9733         pic16_emitcode("mov","a,%s",l);
9734         pic16_aopPut(AOP(result),"a",offset);
9735       } else {
9736
9737         /* we don't know if left is a literal or a register, take care -- VR */
9738         mov2f(AOP(result), AOP(left), offset);
9739       }
9740       offset++;
9741     }
9742   }
9743
9744   size = AOP_SIZE(result);
9745
9746   /* if it is only one byte then */
9747   if (size == 1) {
9748     if(optimized_for_speed) {
9749       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9750       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9751       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9752       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9753       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9754       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9755       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9756       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9757       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9758       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9759       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9760       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9761     } else {
9762
9763       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9764
9765       tlbl = newiTempLabel(NULL);
9766       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9767                 mov2f(AOP(result), AOP(left), 0);
9768                 
9769 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9770 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9771       }
9772
9773       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9774       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9775       pic16_emitpLabel(tlbl->key);
9776       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9777       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9778       emitSKPC;
9779       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9780     }
9781     goto release ;
9782   }
9783     
9784   if (pic16_sameRegs(AOP(left),AOP(result))) {
9785
9786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9787     
9788     tlbl = newiTempLabel(NULL);
9789     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9790     genMultiAsm(POC_RRCF, result, size,1);
9791     pic16_emitpLabel(tlbl->key);
9792     genMultiAsm(POC_RLCF, result, size,0);
9793     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9794     emitSKPC;
9795     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9796     goto release;
9797   }
9798
9799   //tlbl = newiTempLabel(NULL);
9800   //offset = 0 ;   
9801   //tlbl1 = newiTempLabel(NULL);
9802
9803   //reAdjustPreg(AOP(result));    
9804     
9805   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9806   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9807   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9808   //MOVA(l);
9809   //pic16_emitcode("add","a,acc");         
9810   //pic16_aopPut(AOP(result),"a",offset++);
9811   //while (--size) {
9812   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9813   //  MOVA(l);
9814   //  pic16_emitcode("rlc","a");         
9815   //  pic16_aopPut(AOP(result),"a",offset++);
9816   //}
9817   //reAdjustPreg(AOP(result));
9818
9819   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9820   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9821
9822
9823   tlbl = newiTempLabel(NULL);
9824   tlbl1= newiTempLabel(NULL);
9825
9826   size = AOP_SIZE(result);
9827   offset = 1;
9828
9829   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9830
9831   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9832
9833   /* offset should be 0, 1 or 3 */
9834   
9835   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9836   emitSKPNZ;
9837   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9838
9839   pic16_emitpcode(POC_MOVWF, pctemp);
9840
9841
9842   pic16_emitpLabel(tlbl->key);
9843
9844   emitCLRC;
9845   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9846   while(--size)
9847     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9848
9849   pic16_emitpcode(POC_DECFSZ,  pctemp);
9850   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851   pic16_emitpLabel(tlbl1->key);
9852
9853   pic16_popReleaseTempReg(pctemp,1);
9854
9855
9856  release:
9857   pic16_freeAsmop (right,NULL,ic,TRUE);
9858   pic16_freeAsmop(left,NULL,ic,TRUE);
9859   pic16_freeAsmop(result,NULL,ic,TRUE);
9860 }
9861 #endif
9862
9863 /*-----------------------------------------------------------------*/
9864 /* genrshOne - right shift a one byte quantity by known count      */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshOne (operand *result, operand *left,
9867                        int shCount, int sign)
9868 {
9869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9871 }
9872
9873 /*-----------------------------------------------------------------*/
9874 /* genrshTwo - right shift two bytes by known amount != 0          */
9875 /*-----------------------------------------------------------------*/
9876 static void genrshTwo (operand *result,operand *left,
9877                        int shCount, int sign)
9878 {
9879   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9880   /* if shCount >= 8 */
9881   if (shCount >= 8) {
9882     shCount -= 8 ;
9883     if (shCount)
9884       shiftR1Left2Result(left, MSB16, result, LSB,
9885                          shCount, sign);
9886     else
9887       movLeft2Result(left, MSB16, result, LSB);
9888
9889     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9890
9891     if(sign) {
9892       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9893       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9894     }
9895   }
9896
9897   /*  1 <= shCount <= 7 */
9898   else
9899     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9900 }
9901
9902 /*-----------------------------------------------------------------*/
9903 /* shiftRLong - shift right one long from left to result           */
9904 /* offl = LSB or MSB16                                             */
9905 /*-----------------------------------------------------------------*/
9906 static void shiftRLong (operand *left, int offl,
9907                         operand *result, int sign)
9908 {
9909     int size = AOP_SIZE(result);
9910     int same = pic16_sameRegs(AOP(left),AOP(result));
9911     int i;
9912     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9913
9914         if (same && (offl == MSB16)) { //shift one byte right
9915                 for(i=MSB16;i<size;i++) {
9916                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9917                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9918                 }
9919         }
9920
9921     if(sign)
9922                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9923         else
9924                 emitCLRC;
9925
9926         if (same) {
9927                 if (offl == LSB)
9928                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9929         } else {
9930         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9931         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9932         }
9933
9934     if(offl == MSB16) {
9935         /* add sign of "a" */
9936         pic16_addSign(result, MSB32, sign);
9937         }
9938
9939         if (same) {
9940         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9941         } else {
9942         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9943         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9944         }
9945         
9946         if (same) {
9947         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9948         } else {
9949         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9950         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9951         }
9952
9953         if (same) {
9954         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9955         } else {
9956         if(offl == LSB){
9957                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9958                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9959         }
9960         }
9961 }
9962
9963 /*-----------------------------------------------------------------*/
9964 /* genrshFour - shift four byte by a known amount != 0             */
9965 /*-----------------------------------------------------------------*/
9966 static void genrshFour (operand *result, operand *left,
9967                         int shCount, int sign)
9968 {
9969   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9970   /* if shifting more that 3 bytes */
9971   if(shCount >= 24 ) {
9972     shCount -= 24;
9973     if(shCount)
9974       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9975     else
9976       movLeft2Result(left, MSB32, result, LSB);
9977
9978     pic16_addSign(result, MSB16, sign);
9979   }
9980   else if(shCount >= 16){
9981     shCount -= 16;
9982     if(shCount)
9983       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9984     else{
9985       movLeft2Result(left, MSB24, result, LSB);
9986       movLeft2Result(left, MSB32, result, MSB16);
9987     }
9988     pic16_addSign(result, MSB24, sign);
9989   }
9990   else if(shCount >= 8){
9991     shCount -= 8;
9992     if(shCount == 1)
9993       shiftRLong(left, MSB16, result, sign);
9994     else if(shCount == 0){
9995       movLeft2Result(left, MSB16, result, LSB);
9996       movLeft2Result(left, MSB24, result, MSB16);
9997       movLeft2Result(left, MSB32, result, MSB24);
9998       pic16_addSign(result, MSB32, sign);
9999     }
10000     else{ //shcount >= 2
10001       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10002       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10003       /* the last shift is signed */
10004       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10005       pic16_addSign(result, MSB32, sign);
10006     }
10007   }
10008   else{   /* 1 <= shCount <= 7 */
10009     if(shCount <= 2){
10010       shiftRLong(left, LSB, result, sign);
10011       if(shCount == 2)
10012         shiftRLong(result, LSB, result, sign);
10013     }
10014     else{
10015       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10016       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10017       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10018     }
10019   }
10020 }
10021
10022 /*-----------------------------------------------------------------*/
10023 /* genRightShiftLiteral - right shifting by known count            */
10024 /*-----------------------------------------------------------------*/
10025 static void genRightShiftLiteral (operand *left,
10026                                   operand *right,
10027                                   operand *result,
10028                                   iCode *ic,
10029                                   int sign)
10030 {    
10031   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10032   int lsize,res_size;
10033
10034   pic16_freeAsmop(right,NULL,ic,TRUE);
10035
10036   pic16_aopOp(left,ic,FALSE);
10037   pic16_aopOp(result,ic,TRUE);
10038
10039   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10040
10041 #if VIEW_SIZE
10042   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10043                  AOP_SIZE(left));
10044 #endif
10045
10046   lsize = pic16_getDataSize(left);
10047   res_size = pic16_getDataSize(result);
10048   /* test the LEFT size !!! */
10049
10050   /* I suppose that the left size >= result size */
10051   if(shCount == 0){
10052     assert (res_size <= lsize);
10053     while (res_size--) {
10054       mov2f (AOP(result), AOP(left), res_size);
10055     } // for
10056   }
10057
10058   else if(shCount >= (lsize * 8)){
10059
10060     if(res_size == 1) {
10061       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10062       if(sign) {
10063         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10064         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10065       }
10066     } else {
10067
10068       if(sign) {
10069         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10070         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10071         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10072         while(res_size--)
10073           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10074
10075       } else {
10076
10077         while(res_size--)
10078           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10079       }
10080     }
10081   } else {
10082
10083     switch (res_size) {
10084     case 1:
10085       genrshOne (result,left,shCount,sign);
10086       break;
10087
10088     case 2:
10089       genrshTwo (result,left,shCount,sign);
10090       break;
10091
10092     case 4:
10093       genrshFour (result,left,shCount,sign);
10094       break;
10095     default :
10096       break;
10097     }
10098
10099   }
10100
10101   pic16_freeAsmop(left,NULL,ic,TRUE);
10102   pic16_freeAsmop(result,NULL,ic,TRUE);
10103 }
10104
10105 #if !(USE_GENERIC_SIGNED_SHIFT)
10106 /*-----------------------------------------------------------------*/
10107 /* genSignedRightShift - right shift of signed number              */
10108 /*-----------------------------------------------------------------*/
10109 static void genSignedRightShift (iCode *ic)
10110 {
10111   operand *right, *left, *result;
10112   int size, offset;
10113   //  char *l;
10114   symbol *tlbl, *tlbl1 ;
10115   pCodeOp *pctemp;
10116
10117   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10118
10119   /* we do it the hard way put the shift count in b
10120      and loop thru preserving the sign */
10121   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10122
10123   right = IC_RIGHT(ic);
10124   left  = IC_LEFT(ic);
10125   result = IC_RESULT(ic);
10126
10127   pic16_aopOp(right,ic,FALSE);  
10128   pic16_aopOp(left,ic,FALSE);
10129   pic16_aopOp(result,ic,FALSE);
10130
10131
10132   if ( AOP_TYPE(right) == AOP_LIT) {
10133     genRightShiftLiteral (left,right,result,ic,1);
10134     return ;
10135   }
10136   /* shift count is unknown then we have to form 
10137      a loop get the loop count in B : Note: we take
10138      only the lower order byte since shifting
10139      more that 32 bits make no sense anyway, ( the
10140      largest size of an object can be only 32 bits ) */  
10141
10142   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10143   //pic16_emitcode("inc","b");
10144   //pic16_freeAsmop (right,NULL,ic,TRUE);
10145   //pic16_aopOp(left,ic,FALSE);
10146   //pic16_aopOp(result,ic,FALSE);
10147
10148   /* now move the left to the result if they are not the
10149      same */
10150   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10151       AOP_SIZE(result) > 1) {
10152
10153     size = AOP_SIZE(result);
10154     offset=0;
10155     while (size--) { 
10156       /*
10157         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10158         if (*l == '@' && IS_AOP_PREG(result)) {
10159
10160         pic16_emitcode("mov","a,%s",l);
10161         pic16_aopPut(AOP(result),"a",offset);
10162         } else
10163         pic16_aopPut(AOP(result),l,offset);
10164       */
10165       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10166       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10167
10168       offset++;
10169     }
10170   }
10171
10172   /* mov the highest order bit to OVR */    
10173   tlbl = newiTempLabel(NULL);
10174   tlbl1= newiTempLabel(NULL);
10175
10176   size = AOP_SIZE(result);
10177   offset = size - 1;
10178
10179   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10180
10181   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10182
10183   /* offset should be 0, 1 or 3 */
10184   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10185   emitSKPNZ;
10186   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10187
10188   pic16_emitpcode(POC_MOVWF, pctemp);
10189
10190
10191   pic16_emitpLabel(tlbl->key);
10192
10193   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10194   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10195
10196   while(--size) {
10197     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10198   }
10199
10200   pic16_emitpcode(POC_DECFSZ,  pctemp);
10201   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10202   pic16_emitpLabel(tlbl1->key);
10203
10204   pic16_popReleaseTempReg(pctemp,1);
10205 #if 0
10206   size = AOP_SIZE(result);
10207   offset = size - 1;
10208   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10209   pic16_emitcode("rlc","a");
10210   pic16_emitcode("mov","ov,c");
10211   /* if it is only one byte then */
10212   if (size == 1) {
10213     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10214     MOVA(l);
10215     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10216     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10217     pic16_emitcode("mov","c,ov");
10218     pic16_emitcode("rrc","a");
10219     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10220     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10221     pic16_aopPut(AOP(result),"a",0);
10222     goto release ;
10223   }
10224
10225   reAdjustPreg(AOP(result));
10226   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10227   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10228   pic16_emitcode("mov","c,ov");
10229   while (size--) {
10230     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10231     MOVA(l);
10232     pic16_emitcode("rrc","a");         
10233     pic16_aopPut(AOP(result),"a",offset--);
10234   }
10235   reAdjustPreg(AOP(result));
10236   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10237   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10238
10239  release:
10240 #endif
10241
10242   pic16_freeAsmop(left,NULL,ic,TRUE);
10243   pic16_freeAsmop(result,NULL,ic,TRUE);
10244   pic16_freeAsmop(right,NULL,ic,TRUE);
10245 }
10246 #endif
10247
10248 #if !(USE_GENERIC_SIGNED_SHIFT)
10249 #warning This implementation of genRightShift() is incomplete!
10250 /*-----------------------------------------------------------------*/
10251 /* genRightShift - generate code for right shifting                */
10252 /*-----------------------------------------------------------------*/
10253 static void genRightShift (iCode *ic)
10254 {
10255     operand *right, *left, *result;
10256     sym_link *letype ;
10257     int size, offset;
10258     char *l;
10259     symbol *tlbl, *tlbl1 ;
10260
10261     /* if signed then we do it the hard way preserve the
10262     sign bit moving it inwards */
10263     letype = getSpec(operandType(IC_LEFT(ic)));
10264     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10265
10266     if (!SPEC_USIGN(letype)) {
10267         genSignedRightShift (ic);
10268         return ;
10269     }
10270
10271     /* signed & unsigned types are treated the same : i.e. the
10272     signed is NOT propagated inwards : quoting from the
10273     ANSI - standard : "for E1 >> E2, is equivalent to division
10274     by 2**E2 if unsigned or if it has a non-negative value,
10275     otherwise the result is implementation defined ", MY definition
10276     is that the sign does not get propagated */
10277
10278     right = IC_RIGHT(ic);
10279     left  = IC_LEFT(ic);
10280     result = IC_RESULT(ic);
10281
10282     pic16_aopOp(right,ic,FALSE);
10283
10284     /* if the shift count is known then do it 
10285     as efficiently as possible */
10286     if (AOP_TYPE(right) == AOP_LIT) {
10287         genRightShiftLiteral (left,right,result,ic, 0);
10288         return ;
10289     }
10290
10291     /* shift count is unknown then we have to form 
10292     a loop get the loop count in B : Note: we take
10293     only the lower order byte since shifting
10294     more that 32 bits make no sense anyway, ( the
10295     largest size of an object can be only 32 bits ) */  
10296
10297     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10298     pic16_emitcode("inc","b");
10299     pic16_aopOp(left,ic,FALSE);
10300     pic16_aopOp(result,ic,FALSE);
10301
10302     /* now move the left to the result if they are not the
10303     same */
10304     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10305         AOP_SIZE(result) > 1) {
10306
10307         size = AOP_SIZE(result);
10308         offset=0;
10309         while (size--) {
10310             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10311             if (*l == '@' && IS_AOP_PREG(result)) {
10312
10313                 pic16_emitcode("mov","a,%s",l);
10314                 pic16_aopPut(AOP(result),"a",offset);
10315             } else
10316                 pic16_aopPut(AOP(result),l,offset);
10317             offset++;
10318         }
10319     }
10320
10321     tlbl = newiTempLabel(NULL);
10322     tlbl1= newiTempLabel(NULL);
10323     size = AOP_SIZE(result);
10324     offset = size - 1;
10325
10326     /* if it is only one byte then */
10327     if (size == 1) {
10328
10329       tlbl = newiTempLabel(NULL);
10330       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10331         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10332         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10333       }
10334
10335       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10336       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10337       pic16_emitpLabel(tlbl->key);
10338       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10339       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10340       emitSKPC;
10341       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10342
10343       goto release ;
10344     }
10345
10346     reAdjustPreg(AOP(result));
10347     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10348     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10349     CLRC;
10350     while (size--) {
10351         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10352         MOVA(l);
10353         pic16_emitcode("rrc","a");         
10354         pic16_aopPut(AOP(result),"a",offset--);
10355     }
10356     reAdjustPreg(AOP(result));
10357
10358     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10359     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10360
10361 release:
10362     pic16_freeAsmop(left,NULL,ic,TRUE);
10363     pic16_freeAsmop (right,NULL,ic,TRUE);
10364     pic16_freeAsmop(result,NULL,ic,TRUE);
10365 }
10366 #endif
10367
10368 #if (USE_GENERIC_SIGNED_SHIFT)
10369 /*-----------------------------------------------------------------*/
10370 /* genGenericShift - generates code for left or right shifting     */
10371 /*-----------------------------------------------------------------*/
10372 static void genGenericShift (iCode *ic, int isShiftLeft) {
10373   operand *left,*right, *result;
10374   int offset;
10375   int sign, signedCount;
10376   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10377   PIC_OPCODE pos_shift, neg_shift;
10378
10379   FENTRY;
10380
10381   right = IC_RIGHT(ic);
10382   left  = IC_LEFT(ic);
10383   result = IC_RESULT(ic);
10384
10385   pic16_aopOp(right,ic,FALSE);
10386   pic16_aopOp(left,ic,FALSE);
10387   pic16_aopOp(result,ic,TRUE);
10388
10389   sign = !SPEC_USIGN(operandType (left));
10390   signedCount = !SPEC_USIGN(operandType (right));
10391
10392   /* if the shift count is known then do it 
10393      as efficiently as possible */
10394   if (AOP_TYPE(right) == AOP_LIT) {
10395     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10396     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10397     // we should modify right->aopu.aop_lit here!
10398     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10399     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10400     if (isShiftLeft)
10401       pic16_genLeftShiftLiteral (left,right,result,ic);
10402     else
10403       genRightShiftLiteral (left,right,result,ic, sign);
10404
10405     goto release;
10406   } // if (right is literal)
10407
10408   /* shift count is unknown then we have to form a loop.
10409    * Note: we take only the lower order byte since shifting
10410    * more than 32 bits make no sense anyway, ( the
10411    * largest size of an object can be only 32 bits )
10412    * Note: we perform arithmetic shifts if the left operand is
10413    * signed and we do an (effective) right shift, i. e. we
10414    * shift in the sign bit from the left. */
10415    
10416   label_complete = newiTempLabel ( NULL );
10417   label_loop_pos = newiTempLabel ( NULL );
10418   label_loop_neg = NULL;
10419   label_negative = NULL;
10420   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10421   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10422
10423   if (signedCount) {
10424     // additional labels needed
10425     label_loop_neg = newiTempLabel ( NULL );
10426     label_negative = newiTempLabel ( NULL );
10427   } // if
10428
10429   // copy source to result -- this will effectively truncate the left operand to the size of result!
10430   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10431   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10432   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10433     mov2f (AOP(result),AOP(left), offset);
10434   } // for
10435
10436   // if result is longer than left, fill with zeros (or sign)
10437   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10438     if (sign && AOP_SIZE(left) > 0) {
10439       // shift signed operand -- fill with sign
10440       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10441       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10442       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10443       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10444         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10445       } // for
10446     } else {
10447       // shift unsigned operand -- fill result with zeros
10448       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10449         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10450       } // for
10451     }
10452   } // if (size mismatch)
10453
10454   pic16_mov2w (AOP(right), 0);
10455   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10456   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10457   
10458 #if 0
10459   // perform a shift by one (shift count is positive)
10460   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10461   // 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])
10462   pic16_emitpLabel (label_loop_pos->key);
10463   emitCLRC;
10464   if (sign && (pos_shift == POC_RRCF)) {
10465     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10466     emitSETC;
10467   } // if
10468   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10469   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10470   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10471 #else
10472   // perform a shift by one (shift count is positive)
10473   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10474   // 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])
10475   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10476   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10477   emitCLRC;
10478   pic16_emitpLabel (label_loop_pos->key);
10479   if (sign && (pos_shift == POC_RRCF)) {
10480     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10481     emitSETC;
10482   } // if
10483   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10484   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10485   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10486   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10487 #endif
10488
10489   if (signedCount) {
10490     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10491
10492     pic16_emitpLabel (label_negative->key);
10493     // perform a shift by -1 (shift count is negative)
10494     // 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)
10495     emitCLRC;
10496     pic16_emitpLabel (label_loop_neg->key);
10497     if (sign && (neg_shift == POC_RRCF)) {
10498       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10499       emitSETC;
10500     } // if
10501     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10502     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10503     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10504     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10505   } // if (signedCount)
10506
10507   pic16_emitpLabel (label_complete->key);
10508
10509 release:
10510   pic16_freeAsmop (right,NULL,ic,TRUE);
10511   pic16_freeAsmop(left,NULL,ic,TRUE);
10512   pic16_freeAsmop(result,NULL,ic,TRUE);
10513 }
10514
10515 static void genLeftShift (iCode *ic) {
10516   genGenericShift (ic, 1);
10517 }
10518
10519 static void genRightShift (iCode *ic) {
10520   genGenericShift (ic, 0);
10521 }
10522 #endif
10523
10524
10525 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10526 void pic16_loadFSR0(operand *op, int lit)
10527 {
10528   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10529     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10530   } else {
10531     assert (!OP_SYMBOL(op)->remat);
10532     // set up FSR0 with address of result
10533     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10534     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10535   }
10536 }
10537
10538 /*-----------------------------------------------------------------*/
10539 /* genUnpackBits - generates code for unpacking bits               */
10540 /*-----------------------------------------------------------------*/
10541 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10542 {    
10543   int shCnt ;
10544   int rlen = 0 ;
10545   sym_link *etype, *letype;
10546   int blen=0, bstr=0;
10547   int lbstr;
10548   int offset = 0 ;
10549
10550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10551     etype = getSpec(operandType(result));
10552     letype = getSpec(operandType(left));
10553     
10554 //    if(IS_BITFIELD(etype)) {
10555       blen = SPEC_BLEN(etype);
10556       bstr = SPEC_BSTR(etype);
10557 //    }
10558
10559     lbstr = SPEC_BSTR( letype );
10560
10561 #if 1
10562     if((blen == 1) && (bstr < 8)) {
10563       /* it is a single bit, so use the appropriate bit instructions */
10564       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10565
10566       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10567       
10568       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10569       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10570         /* workaround to reduce the extra lfsr instruction */
10571         pic16_emitpcode(POC_BTFSC,
10572               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10573       } else {
10574         pic16_loadFSR0 (left, 0);
10575         pic16_emitpcode(POC_BTFSC,
10576               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10577       }
10578         
10579       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10580
10581       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10582       return;
10583     }
10584
10585 #endif
10586
10587         /* the following call to pic16_loadFSR0 is temporary until
10588          * optimization to handle single bit assignments is added
10589          * to the function. Until then use the old safe way! -- VR */
10590
10591     if (OP_SYMBOL(left)->remat) {
10592         // access symbol directly
10593         pic16_mov2w (AOP(left), 0);
10594     } else {
10595         pic16_loadFSR0( left, 0 );
10596  
10597         /* read the first byte  */
10598         switch (ptype) {
10599                 case POINTER:
10600                 case IPOINTER:
10601                 case PPOINTER:
10602                 case FPOINTER:
10603                 case GPOINTER:
10604                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10605                         break;
10606                 case CPOINTER:
10607                         pic16_emitcode("clr","a");
10608                         pic16_emitcode("movc","a","@a+dptr");
10609                         assert (0);
10610                         break;
10611         }
10612     }
10613
10614         /* if we have bitdisplacement then it fits   */
10615         /* into this byte completely or if length is */
10616         /* less than a byte                          */
10617         if ((shCnt = SPEC_BSTR(etype)) || 
10618                 (SPEC_BLEN(etype) <= 8))  {
10619
10620                 /* shift right acc */
10621                 AccRsh(shCnt, 0);
10622
10623                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10624                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10625
10626 /* VR -- normally I would use the following, but since we use the hack,
10627  * to avoid the masking from AccRsh, why not mask it right now? */
10628
10629 /*
10630                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10631 */
10632
10633                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10634           return ;
10635         }
10636
10637
10638
10639         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10640         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10641         exit(-1);
10642
10643     /* bit field did not fit in a byte  */
10644     rlen = SPEC_BLEN(etype) - 8;
10645     pic16_aopPut(AOP(result),"a",offset++);
10646
10647     while (1)  {
10648
10649         switch (ptype) {
10650         case POINTER:
10651         case IPOINTER:
10652             pic16_emitcode("inc","%s",rname);
10653             pic16_emitcode("mov","a,@%s",rname);
10654             break;
10655             
10656         case PPOINTER:
10657             pic16_emitcode("inc","%s",rname);
10658             pic16_emitcode("movx","a,@%s",rname);
10659             break;
10660
10661         case FPOINTER:
10662             pic16_emitcode("inc","dptr");
10663             pic16_emitcode("movx","a,@dptr");
10664             break;
10665             
10666         case CPOINTER:
10667             pic16_emitcode("clr","a");
10668             pic16_emitcode("inc","dptr");
10669             pic16_emitcode("movc","a","@a+dptr");
10670             break;
10671             
10672         case GPOINTER:
10673             pic16_emitcode("inc","dptr");
10674             pic16_emitcode("lcall","__gptrget");
10675             break;
10676         }
10677
10678         rlen -= 8;            
10679         /* if we are done */
10680         if ( rlen <= 0 )
10681             break ;
10682         
10683         pic16_aopPut(AOP(result),"a",offset++);
10684                               
10685     }
10686     
10687     if (rlen) {
10688         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10689         pic16_aopPut(AOP(result),"a",offset);          
10690     }
10691     
10692     return ;
10693 }
10694
10695
10696 static void genDataPointerGet(operand *left,
10697                               operand *result,
10698                               iCode *ic)
10699 {
10700   int size, offset = 0, leoffset=0 ;
10701
10702         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10703         pic16_aopOp(result, ic, TRUE);
10704
10705         FENTRY;
10706
10707         size = AOP_SIZE(result);
10708 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10709
10710
10711 #if 0
10712         /* The following tests may save a redudant movff instruction when
10713          * accessing unions */
10714          
10715         /* if they are the same */
10716         if (operandsEqu (left, result)) {
10717                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10718                 goto release;
10719         }
10720 #endif
10721
10722 #if 0
10723         /* if they are the same registers */
10724         if (pic16_sameRegs(AOP(left),AOP(result))) {
10725                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10726                 goto release;
10727         }
10728 #endif
10729
10730 #if 1
10731         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10732                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10733                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10734                 goto release;
10735         }
10736 #endif
10737
10738
10739 #if 0
10740         if ( AOP_TYPE(left) == AOP_PCODE) {
10741                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10742                                 AOP(left)->aopu.pcop->name,
10743                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10744                                 PCOR(AOP(left)->aopu.pcop)->instance:
10745                                 PCOI(AOP(left)->aopu.pcop)->offset);
10746         }
10747 #endif
10748
10749         if(AOP(left)->aopu.pcop->type == PO_DIR)
10750                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10751
10752         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10753
10754         while (size--) {
10755                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10756                 
10757 //              pic16_DumpOp("(result)",result);
10758                 if(is_LitAOp(AOP(result))) {
10759                         pic16_mov2w(AOP(left), offset); // patch 8
10760                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10761                 } else {
10762                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10763                                 pic16_popGet(AOP(left), offset), //patch 8
10764                                 pic16_popGet(AOP(result), offset)));
10765                 }
10766
10767                 offset++;
10768                 leoffset++;
10769         }
10770
10771 release:
10772     pic16_freeAsmop(result,NULL,ic,TRUE);
10773 }
10774
10775
10776
10777 /*-----------------------------------------------------------------*/
10778 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10779 /*-----------------------------------------------------------------*/
10780 static void genNearPointerGet (operand *left, 
10781                                operand *result, 
10782                                iCode *ic)
10783 {
10784 //  asmop *aop = NULL;
10785   //regs *preg = NULL ;
10786   sym_link *rtype, *retype;
10787   sym_link *ltype = operandType(left);    
10788
10789     FENTRY;
10790     
10791     rtype = operandType(result);
10792     retype= getSpec(rtype);
10793     
10794     pic16_aopOp(left,ic,FALSE);
10795
10796 //    pic16_DumpOp("(left)",left);
10797 //    pic16_DumpOp("(result)",result);
10798
10799     /* if left is rematerialisable and
10800      * result is not bit variable type and
10801      * the left is pointer to data space i.e
10802      * lower 128 bytes of space */
10803     
10804     if (AOP_TYPE(left) == AOP_PCODE
10805       && !IS_BITFIELD(retype)
10806       && DCL_TYPE(ltype) == POINTER) {
10807
10808         genDataPointerGet (left,result,ic);
10809         pic16_freeAsmop(left, NULL, ic, TRUE);
10810         return ;
10811     }
10812     
10813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10814     pic16_aopOp (result,ic,TRUE);
10815     
10816     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10817
10818 #if 1
10819     if(IS_BITFIELD( retype )
10820       && (SPEC_BLEN(operandType(result))==1)
10821     ) {
10822       iCode *nextic;
10823       pCodeOp *jop;
10824       int bitstrt, bytestrt;
10825
10826         /* if this is bitfield of size 1, see if we are checking the value
10827          * of a single bit in an if-statement,
10828          * if yes, then don't generate usual code, but execute the
10829          * genIfx directly -- VR */
10830
10831         nextic = ic->next;
10832
10833         /* CHECK: if next iCode is IFX
10834          * and current result operand is nextic's conditional operand
10835          * and current result operand live ranges ends at nextic's key number
10836          */
10837         if((nextic->op == IFX)
10838           && (result == IC_COND(nextic))
10839           && (OP_LIVETO(result) == nextic->seq)
10840           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10841           ) {
10842             /* everything is ok then */
10843             /* find a way to optimize the genIfx iCode */
10844
10845             bytestrt = SPEC_BSTR(operandType(result))/8;
10846             bitstrt = SPEC_BSTR(operandType(result))%8;
10847             
10848             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10849
10850             genIfxpCOpJump(nextic, jop);
10851             
10852             pic16_freeAsmop(left, NULL, ic, TRUE);
10853             pic16_freeAsmop(result, NULL, ic, TRUE);
10854             return;
10855         }
10856     }
10857 #endif
10858
10859
10860     /* if the value is already in a pointer register
10861      * then don't need anything more */
10862     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
10863       /* otherwise get a free pointer register */
10864       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10865                 
10866       ;
10867     }
10868
10869     /* if bitfield then unpack the bits */
10870     if (IS_BITFIELD(retype)) 
10871       genUnpackBits (result, left, NULL, POINTER);
10872     else {
10873       /* we have can just get the values */
10874       int size = AOP_SIZE(result);
10875       int offset = 0;   
10876         
10877       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10878
10879       pic16_loadFSR0( left, 0 );
10880
10881       while(size--) {
10882         if(size) {
10883           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10884                 pic16_popGet(AOP(result), offset++)));
10885         } else {
10886           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10887                 pic16_popGet(AOP(result), offset++)));
10888         }
10889       }
10890     }
10891
10892 #if 0
10893     /* now some housekeeping stuff */
10894     if (aop) {
10895       /* we had to allocate for this iCode */
10896       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10897       pic16_freeAsmop(NULL,aop,ic,TRUE);
10898     } else { 
10899       /* we did not allocate which means left
10900        * already in a pointer register, then
10901        * if size > 0 && this could be used again
10902        * we have to point it back to where it 
10903        * belongs */
10904       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10905       if (AOP_SIZE(result) > 1
10906         && !OP_SYMBOL(left)->remat
10907         && ( OP_SYMBOL(left)->liveTo > ic->seq
10908             || ic->depth )) {
10909 //        int size = AOP_SIZE(result) - 1;
10910 //        while (size--)
10911 //          pic16_emitcode("dec","%s",rname);
10912         }
10913     }
10914 #endif
10915
10916     /* done */
10917     pic16_freeAsmop(left,NULL,ic,TRUE);
10918     pic16_freeAsmop(result,NULL,ic,TRUE);
10919 }
10920
10921 /*-----------------------------------------------------------------*/
10922 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10923 /*-----------------------------------------------------------------*/
10924 static void genPagedPointerGet (operand *left, 
10925                                operand *result, 
10926                                iCode *ic)
10927 {
10928     asmop *aop = NULL;
10929     regs *preg = NULL ;
10930     char *rname ;
10931     sym_link *rtype, *retype;    
10932
10933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10934
10935     rtype = operandType(result);
10936     retype= getSpec(rtype);
10937     
10938     pic16_aopOp(left,ic,FALSE);
10939
10940   /* if the value is already in a pointer register
10941        then don't need anything more */
10942     if (!AOP_INPREG(AOP(left))) {
10943         /* otherwise get a free pointer register */
10944         aop = newAsmop(0);
10945         preg = getFreePtr(ic,&aop,FALSE);
10946         pic16_emitcode("mov","%s,%s",
10947                 preg->name,
10948                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10949         rname = preg->name ;
10950     } else
10951         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10952     
10953     pic16_freeAsmop(left,NULL,ic,TRUE);
10954     pic16_aopOp (result,ic,TRUE);
10955
10956     /* if bitfield then unpack the bits */
10957     if (IS_BITFIELD(retype)) 
10958         genUnpackBits (result,left,rname,PPOINTER);
10959     else {
10960         /* we have can just get the values */
10961         int size = AOP_SIZE(result);
10962         int offset = 0 ;        
10963         
10964         while (size--) {
10965             
10966             pic16_emitcode("movx","a,@%s",rname);
10967             pic16_aopPut(AOP(result),"a",offset);
10968             
10969             offset++ ;
10970             
10971             if (size)
10972                 pic16_emitcode("inc","%s",rname);
10973         }
10974     }
10975
10976     /* now some housekeeping stuff */
10977     if (aop) {
10978         /* we had to allocate for this iCode */
10979         pic16_freeAsmop(NULL,aop,ic,TRUE);
10980     } else { 
10981         /* we did not allocate which means left
10982            already in a pointer register, then
10983            if size > 0 && this could be used again
10984            we have to point it back to where it 
10985            belongs */
10986         if (AOP_SIZE(result) > 1 &&
10987             !OP_SYMBOL(left)->remat &&
10988             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10989               ic->depth )) {
10990             int size = AOP_SIZE(result) - 1;
10991             while (size--)
10992                 pic16_emitcode("dec","%s",rname);
10993         }
10994     }
10995
10996     /* done */
10997     pic16_freeAsmop(result,NULL,ic,TRUE);
10998     
10999         
11000 }
11001
11002 /*-----------------------------------------------------------------*/
11003 /* genFarPointerGet - gget value from far space                    */
11004 /*-----------------------------------------------------------------*/
11005 static void genFarPointerGet (operand *left,
11006                               operand *result, iCode *ic)
11007 {
11008     int size, offset ;
11009     sym_link *retype = getSpec(operandType(result));
11010
11011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11012
11013     pic16_aopOp(left,ic,FALSE);
11014
11015     /* if the operand is already in dptr 
11016     then we do nothing else we move the value to dptr */
11017     if (AOP_TYPE(left) != AOP_STR) {
11018         /* if this is remateriazable */
11019         if (AOP_TYPE(left) == AOP_IMMD)
11020             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11021         else { /* we need to get it byte by byte */
11022             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11023             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11024             if (options.model == MODEL_FLAT24)
11025             {
11026                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11027             }
11028         }
11029     }
11030     /* so dptr know contains the address */
11031     pic16_freeAsmop(left,NULL,ic,TRUE);
11032     pic16_aopOp(result,ic,TRUE);
11033
11034     /* if bit then unpack */
11035     if (IS_BITFIELD(retype)) 
11036         genUnpackBits(result,left,"dptr",FPOINTER);
11037     else {
11038         size = AOP_SIZE(result);
11039         offset = 0 ;
11040
11041         while (size--) {
11042             pic16_emitcode("movx","a,@dptr");
11043             pic16_aopPut(AOP(result),"a",offset++);
11044             if (size)
11045                 pic16_emitcode("inc","dptr");
11046         }
11047     }
11048
11049     pic16_freeAsmop(result,NULL,ic,TRUE);
11050 }
11051
11052 #if 0
11053 /*-----------------------------------------------------------------*/
11054 /* genCodePointerGet - get value from code space                  */
11055 /*-----------------------------------------------------------------*/
11056 static void genCodePointerGet (operand *left,
11057                                 operand *result, iCode *ic)
11058 {
11059     int size, offset ;
11060     sym_link *retype = getSpec(operandType(result));
11061
11062     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11063
11064     pic16_aopOp(left,ic,FALSE);
11065
11066     /* if the operand is already in dptr 
11067     then we do nothing else we move the value to dptr */
11068     if (AOP_TYPE(left) != AOP_STR) {
11069         /* if this is remateriazable */
11070         if (AOP_TYPE(left) == AOP_IMMD)
11071             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11072         else { /* we need to get it byte by byte */
11073             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11074             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11075             if (options.model == MODEL_FLAT24)
11076             {
11077                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11078             }
11079         }
11080     }
11081     /* so dptr know contains the address */
11082     pic16_freeAsmop(left,NULL,ic,TRUE);
11083     pic16_aopOp(result,ic,FALSE);
11084
11085     /* if bit then unpack */
11086     if (IS_BITFIELD(retype)) 
11087         genUnpackBits(result,left,"dptr",CPOINTER);
11088     else {
11089         size = AOP_SIZE(result);
11090         offset = 0 ;
11091
11092         while (size--) {
11093             pic16_emitcode("clr","a");
11094             pic16_emitcode("movc","a,@a+dptr");
11095             pic16_aopPut(AOP(result),"a",offset++);
11096             if (size)
11097                 pic16_emitcode("inc","dptr");
11098         }
11099     }
11100
11101     pic16_freeAsmop(result,NULL,ic,TRUE);
11102 }
11103 #endif
11104
11105 #if 0
11106 /*-----------------------------------------------------------------*/
11107 /* genGenPointerGet - gget value from generic pointer space        */
11108 /*-----------------------------------------------------------------*/
11109 static void genGenPointerGet (operand *left,
11110                               operand *result, iCode *ic)
11111 {
11112   int size, offset, lit;
11113   sym_link *retype = getSpec(operandType(result));
11114
11115         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11116         pic16_aopOp(left,ic,FALSE);
11117         pic16_aopOp(result,ic,FALSE);
11118         size = AOP_SIZE(result);
11119
11120         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11121
11122         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11123
11124                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11125                 // load FSR0 from immediate
11126                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11127
11128 //              pic16_loadFSR0( left );
11129
11130                 offset = 0;
11131                 while(size--) {
11132                         if(size) {
11133                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11134                         } else {
11135                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11136                         }
11137                         offset++;
11138                 }
11139                 goto release;
11140
11141         }
11142         else { /* we need to get it byte by byte */
11143                 // set up FSR0 with address from left
11144                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11145                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11146                 
11147                 offset = 0 ;
11148
11149                 while(size--) {
11150                         if(size) {
11151                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11152                         } else {
11153                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11154                         }
11155                         offset++;
11156                 }
11157                 goto release;
11158         }
11159
11160   /* if bit then unpack */
11161         if (IS_BITFIELD(retype)) 
11162                 genUnpackBits(result,left,"BAD",GPOINTER);
11163
11164         release:
11165         pic16_freeAsmop(left,NULL,ic,TRUE);
11166         pic16_freeAsmop(result,NULL,ic,TRUE);
11167
11168 }
11169 #endif
11170
11171
11172 /*-----------------------------------------------------------------*/
11173 /* genGenPointerGet - gget value from generic pointer space        */
11174 /*-----------------------------------------------------------------*/
11175 static void genGenPointerGet (operand *left,
11176                               operand *result, iCode *ic)
11177 {
11178   int size, offset, lit;
11179   sym_link *retype = getSpec(operandType(result));
11180   char fgptrget[32];
11181
11182     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11183     pic16_aopOp(left,ic,FALSE);
11184     pic16_aopOp(result,ic,TRUE);
11185     size = AOP_SIZE(result);
11186
11187     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11188
11189     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11190
11191       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11192       // load FSR0 from immediate
11193       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11194
11195       werror(W_POSSBUG2, __FILE__, __LINE__);
11196
11197       offset = 0;
11198       while(size--) {
11199         if(size) {
11200           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11201         } else {
11202           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11203         }
11204         offset++;
11205       }
11206
11207       goto release;
11208
11209     } else { /* we need to get it byte by byte */
11210
11211       /* set up WREG:PRODL:FSR0L with address from left */
11212       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11213       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11214       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11215       
11216       switch( size ) {
11217         case 1: strcpy(fgptrget, "__gptrget1"); break;
11218         case 2: strcpy(fgptrget, "__gptrget2"); break;
11219         case 3: strcpy(fgptrget, "__gptrget3"); break;
11220         case 4: strcpy(fgptrget, "__gptrget4"); break;
11221         default:
11222           werror(W_POSSBUG2, __FILE__, __LINE__);
11223           abort();
11224       }
11225       
11226       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11227       
11228       assignResultValue(result, 1);
11229       
11230       {
11231         symbol *sym;
11232
11233           sym = newSymbol( fgptrget, 0 );
11234           sym->used++;
11235           strcpy(sym->rname, fgptrget);
11236           checkAddSym(&externs, sym);
11237
11238 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11239       }
11240               
11241       goto release;
11242     }
11243
11244   /* if bit then unpack */
11245     if (IS_BITFIELD(retype)) 
11246       genUnpackBits(result,left,"BAD",GPOINTER);
11247
11248 release:
11249   pic16_freeAsmop(left,NULL,ic,TRUE);
11250   pic16_freeAsmop(result,NULL,ic,TRUE);
11251 }
11252
11253 /*-----------------------------------------------------------------*/
11254 /* genConstPointerGet - get value from const generic pointer space */
11255 /*-----------------------------------------------------------------*/
11256 static void genConstPointerGet (operand *left,
11257                                 operand *result, iCode *ic)
11258 {
11259   //sym_link *retype = getSpec(operandType(result));
11260   // symbol *albl = newiTempLabel(NULL);        // patch 15
11261   // symbol *blbl = newiTempLabel(NULL);        //
11262   // PIC_OPCODE poc;                            // patch 15
11263   int size;
11264   int offset = 0;
11265
11266   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11267   pic16_aopOp(left,ic,FALSE);
11268   pic16_aopOp(result,ic,TRUE);
11269   size = AOP_SIZE(result);
11270
11271   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11272
11273   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11274
11275   // set up table pointer
11276   if( (AOP_TYPE(left) == AOP_PCODE) 
11277       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11278           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11279     {
11280       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11281       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11282       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11283       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11284       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11285       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11286   } else {
11287     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11288     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11289     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11290   }
11291
11292   while(size--) {
11293     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11294     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11295     offset++;
11296   }
11297     
11298   pic16_freeAsmop(left,NULL,ic,TRUE);
11299   pic16_freeAsmop(result,NULL,ic,TRUE);
11300 }
11301
11302
11303 /*-----------------------------------------------------------------*/
11304 /* genPointerGet - generate code for pointer get                   */
11305 /*-----------------------------------------------------------------*/
11306 static void genPointerGet (iCode *ic)
11307 {
11308   operand *left, *result ;
11309   sym_link *type, *etype;
11310   int p_type;
11311
11312     FENTRY;
11313     
11314     left = IC_LEFT(ic);
11315     result = IC_RESULT(ic) ;
11316
11317     /* depending on the type of pointer we need to
11318     move it to the correct pointer register */
11319     type = operandType(left);
11320     etype = getSpec(type);
11321
11322 #if 0
11323     if (IS_PTR_CONST(type))
11324 #else
11325     if (IS_CODEPTR(type))
11326 #endif
11327       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11328
11329     /* if left is of type of pointer then it is simple */
11330     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11331       p_type = DCL_TYPE(type);
11332     else {
11333       /* we have to go by the storage class */
11334       p_type = PTR_TYPE(SPEC_OCLS(etype));
11335
11336       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11337
11338       if (SPEC_OCLS(etype)->codesp ) {
11339         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11340         //p_type = CPOINTER ;   
11341       } else
11342       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11343         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11344         /*p_type = FPOINTER ;*/ 
11345       } else
11346       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11347         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11348         /* p_type = PPOINTER; */
11349       } else
11350       if (SPEC_OCLS(etype) == idata ) {
11351         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11352         /* p_type = IPOINTER; */
11353       } else {
11354         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11355         /* p_type = POINTER ; */
11356       }
11357     }
11358
11359     /* now that we have the pointer type we assign
11360     the pointer values */
11361     switch (p_type) {
11362       case POINTER:     
11363       case IPOINTER:
11364         genNearPointerGet (left,result,ic);
11365         break;
11366
11367       case PPOINTER:
11368         genPagedPointerGet(left,result,ic);
11369         break;
11370
11371       case FPOINTER:
11372         genFarPointerGet (left,result,ic);
11373         break;
11374
11375       case CPOINTER:
11376         genConstPointerGet (left,result,ic);
11377         //pic16_emitcodePointerGet (left,result,ic);
11378         break;
11379
11380       case GPOINTER:
11381 #if 0
11382       if (IS_PTR_CONST(type))
11383         genConstPointerGet (left,result,ic);
11384       else
11385 #endif
11386         genGenPointerGet (left,result,ic);
11387       break;
11388
11389     default:
11390       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11391               "genPointerGet: illegal pointer type");
11392     
11393     }
11394 }
11395
11396 /*-----------------------------------------------------------------*/
11397 /* genPackBits - generates code for packed bit storage             */
11398 /*-----------------------------------------------------------------*/
11399 static void genPackBits (sym_link    *etype , operand *result,
11400                          operand *right ,
11401                          char *rname, int p_type)
11402 {
11403   int shCnt = 0 ;
11404   int offset = 0  ;
11405   int rLen = 0 ;
11406   int blen, bstr ;   
11407   sym_link *retype;
11408
11409         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11410         blen = SPEC_BLEN(etype);
11411         bstr = SPEC_BSTR(etype);
11412
11413         retype = getSpec(operandType(right));
11414
11415         if(AOP_TYPE(right) == AOP_LIT) {
11416                 if((blen == 1) && (bstr < 8)) {
11417                   unsigned long lit;
11418                         /* it is a single bit, so use the appropriate bit instructions */
11419
11420                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11421
11422                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11423 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11424                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11425                                 /* workaround to reduce the extra lfsr instruction */
11426                                 if(lit) {
11427                                         pic16_emitpcode(POC_BSF,
11428                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11429                                 } else {
11430                                         pic16_emitpcode(POC_BCF,
11431                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11432                                 }
11433                         } else {
11434                                 pic16_loadFSR0(result, 0);
11435                                 if(lit) {
11436                                         pic16_emitpcode(POC_BSF,
11437                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11438                                 } else {
11439                                         pic16_emitpcode(POC_BCF,
11440                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11441                                 }
11442                         }
11443         
11444                   return;
11445                 }
11446                 /* move literal to W */
11447                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11448                 offset++;
11449         } else
11450         if(IS_BITFIELD(retype) 
11451           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11452           && (blen == 1)) {
11453           int rblen, rbstr;
11454
11455             rblen = SPEC_BLEN( retype );
11456             rbstr = SPEC_BSTR( retype );
11457             
11458
11459             if(IS_BITFIELD(etype)) {
11460               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11461               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11462             } else {
11463               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11464             }
11465             
11466             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11467             
11468             if(IS_BITFIELD(etype)) {
11469               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11470             } else {
11471               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11472             }
11473
11474             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11475             
11476             return;
11477         } else {
11478           /* move right to W */
11479           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11480         }
11481
11482         /* if the bit length is less than or   */
11483         /* it exactly fits a byte then         */
11484         if((shCnt=SPEC_BSTR(etype))
11485                 || SPEC_BLEN(etype) <= 8 )  {
11486                 int fsr0_setup = 0;
11487
11488                 if (blen != 8 || bstr != 0) {
11489                   // we need to combine the value with the old value
11490                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11491
11492           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11493                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11494                 
11495                   /* shift left acc */
11496                   AccLsh(shCnt);
11497
11498                   /* using PRODH as a temporary register here */
11499                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11500
11501                  if (OP_SYMBOL(result)->remat) {
11502                    // access symbol directly
11503                    pic16_mov2w (AOP(result), 0);
11504                  } else {
11505                   /* get old value */
11506                   switch (p_type) {
11507                         case FPOINTER:
11508                         case POINTER:
11509                                 pic16_loadFSR0( result, 0 );
11510                                 fsr0_setup = 1;
11511                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11512 //                              pic16_emitcode ("mov","b,a");
11513 //                              pic16_emitcode("mov","a,@%s",rname);
11514                                 break;
11515
11516                         case GPOINTER:
11517                                 if (AOP(result)->aopu.aop_reg[2]) {
11518                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11519                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11520                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11521                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11522                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11523                                   {
11524                                     symbol *sym;
11525                                     sym = newSymbol( "__gptrget1", 0 );
11526                                     strcpy(sym->rname, "__gptrget1");
11527                                     checkAddSym(&externs, sym);
11528                                   }
11529                                 } else {
11530                                   // data pointer (just 2 byte given)
11531                                   pic16_loadFSR0( result, 0 );
11532                                   fsr0_setup = 1;
11533                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11534                                 }
11535                                 
11536                                 // warnings will be emitted below
11537                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11538                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11539                                 break;
11540
11541                         default:
11542                                 assert (0 && "invalid pointer type specified");
11543                                 break;
11544                   }
11545                  }
11546 #if 1
11547                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11548                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11549                                         (unsigned char)(0xff >> (8-bstr))) ));
11550                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11551                 } // if (blen != 8 || bstr != 0)
11552
11553                 /* write new value back */
11554                if (OP_SYMBOL(result)->remat) {
11555                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11556                } else {
11557                 switch (p_type) {
11558                         case FPOINTER:
11559                         case POINTER:
11560                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11561                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11562                                 break;
11563
11564                         case GPOINTER:
11565                                 if (AOP(result)->aopu.aop_reg[2]) {
11566                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11567                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11568                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11569                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11570                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11571                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11572                                   {
11573                                     symbol *sym;
11574                                     sym = newSymbol( "__gptrput1", 0 );
11575                                     strcpy(sym->rname, "__gptrput1");
11576                                     checkAddSym(&externs, sym);
11577                                   }
11578                                 } else {
11579                                   // data pointer (just 2 byte given)
11580                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11581                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11582                                 }
11583                                 
11584                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11585                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11586                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11587                                 break;
11588
11589                         default:
11590                                 assert (0 && "invalid pointer type specified");
11591                                 break;
11592                 }
11593                }
11594 #endif
11595
11596           return;
11597         }
11598
11599
11600 #if 0
11601         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11602         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11603         exit(-1);
11604 #endif
11605
11606
11607     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11608     rLen = SPEC_BLEN(etype)-8;
11609     
11610     /* now generate for lengths greater than one byte */
11611     while (1) {
11612         rLen -= 8 ;
11613         if (rLen <= 0 ) {
11614           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11615           break ;
11616         }
11617
11618         switch (p_type) {
11619             case POINTER:
11620                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11621                 break;
11622
11623 /*
11624             case FPOINTER:
11625                 MOVA(l);
11626                 pic16_emitcode("movx","@dptr,a");
11627                 break;
11628
11629             case GPOINTER:
11630                 MOVA(l);
11631                 DEBUGpic16_emitcode(";lcall","__gptrput");
11632                 break;  
11633 */
11634           default:
11635             assert(0);
11636         }   
11637
11638
11639         pic16_mov2w(AOP(right), offset++);
11640     }
11641
11642     /* last last was not complete */
11643     if (rLen)   {
11644         /* save the byte & read byte */
11645         switch (p_type) {
11646             case POINTER:
11647 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11648                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11649                 break;
11650
11651 /*
11652             case FPOINTER:
11653                 pic16_emitcode ("mov","b,a");
11654                 pic16_emitcode("movx","a,@dptr");
11655                 break;
11656
11657             case GPOINTER:
11658                 pic16_emitcode ("push","b");
11659                 pic16_emitcode ("push","acc");
11660                 pic16_emitcode ("lcall","__gptrget");
11661                 pic16_emitcode ("pop","b");
11662                 break;
11663 */
11664             default:
11665               assert(0);
11666         }
11667         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11668         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11669         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11670 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11671 //        pic16_emitcode ("orl","a,b");
11672     }
11673
11674 //    if (p_type == GPOINTER)
11675 //        pic16_emitcode("pop","b");
11676
11677     switch (p_type) {
11678
11679       case POINTER:
11680         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11681 //      pic16_emitcode("mov","@%s,a",rname);
11682         break;
11683 /*
11684       case FPOINTER:
11685         pic16_emitcode("movx","@dptr,a");
11686         break;
11687         
11688       case GPOINTER:
11689         DEBUGpic16_emitcode(";lcall","__gptrput");
11690         break;                  
11691 */
11692       default:
11693         assert(0);
11694     }
11695     
11696 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11697 }
11698 /*-----------------------------------------------------------------*/
11699 /* genDataPointerSet - remat pointer to data space                 */
11700 /*-----------------------------------------------------------------*/
11701 static void genDataPointerSet(operand *right,
11702                               operand *result,
11703                               iCode *ic)
11704 {
11705     int size, offset = 0, resoffset=0 ;
11706
11707     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11708     pic16_aopOp(right,ic,FALSE);
11709
11710     size = AOP_SIZE(right);
11711
11712 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11713
11714 #if 0
11715     if ( AOP_TYPE(result) == AOP_PCODE) {
11716       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11717               AOP(result)->aopu.pcop->name,
11718                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11719               PCOR(AOP(result)->aopu.pcop)->instance:
11720               PCOI(AOP(result)->aopu.pcop)->offset);
11721     }
11722 #endif
11723
11724         if(AOP(result)->aopu.pcop->type == PO_DIR)
11725                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11726
11727         while (size--) {
11728                 if (AOP_TYPE(right) == AOP_LIT) {
11729                   unsigned int lit;
11730
11731                     if(!IS_FLOAT(operandType( right )))
11732                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11733                     else {
11734                       union {
11735                         unsigned long lit_int;
11736                         float lit_float;
11737                       } info;
11738         
11739                         /* take care if literal is a float */
11740                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11741                         lit = info.lit_int;
11742                     }
11743
11744                     lit = lit >> (8*offset);
11745                     if(lit&0xff) {
11746                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11747                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11748                     } else {
11749                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11750                     }
11751                 } else {
11752                   pic16_mov2w(AOP(right), offset);
11753                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11754                 }
11755                 offset++;
11756                 resoffset++;
11757         }
11758
11759     pic16_freeAsmop(right,NULL,ic,TRUE);
11760 }
11761
11762
11763
11764 /*-----------------------------------------------------------------*/
11765 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11766 /*-----------------------------------------------------------------*/
11767 static void genNearPointerSet (operand *right,
11768                                operand *result, 
11769                                iCode *ic)
11770 {
11771   asmop *aop = NULL;
11772   sym_link *retype;
11773   sym_link *ptype = operandType(result);
11774   sym_link *resetype;
11775     
11776         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11777         retype= getSpec(operandType(right));
11778         resetype = getSpec(operandType(result));
11779   
11780         pic16_aopOp(result,ic,FALSE);
11781     
11782         /* if the result is rematerializable &
11783          * in data space & not a bit variable */
11784         
11785         /* and result is not a bit variable */
11786         if (AOP_TYPE(result) == AOP_PCODE
11787 //              && AOP_TYPE(result) == AOP_IMMD
11788                 && DCL_TYPE(ptype) == POINTER
11789                 && !IS_BITFIELD(retype)
11790                 && !IS_BITFIELD(resetype)) {
11791
11792                 genDataPointerSet (right,result,ic);
11793                 pic16_freeAsmop(result,NULL,ic,TRUE);
11794           return;
11795         }
11796
11797         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11798         pic16_aopOp(right,ic,FALSE);
11799         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11800
11801         /* if the value is already in a pointer register
11802          * then don't need anything more */
11803         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11804           /* otherwise get a free pointer register */
11805           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11806
11807           ;
11808         }
11809
11810         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11811
11812         /* if bitfield then unpack the bits */
11813         if (IS_BITFIELD(resetype)) {
11814                 genPackBits (resetype, result, right, NULL, POINTER);
11815         } else {
11816                 /* we have can just get the values */
11817           int size = AOP_SIZE(right);
11818           int offset = 0 ;    
11819
11820             pic16_loadFSR0(result, 0);
11821             
11822                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11823                 while (size--) {
11824                                 if (AOP_TYPE(right) == AOP_LIT) {
11825                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11826                                         if (size) {
11827                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11828                                         } else {
11829                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11830                                         }
11831                                 } else { // no literal
11832                                         if(size) {
11833                                                 pic16_emitpcode(POC_MOVFF,
11834                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11835                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11836                                         } else {
11837                                                 pic16_emitpcode(POC_MOVFF,
11838                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11839                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11840                                         }
11841                                 }
11842                         offset++;
11843                 }
11844         }
11845
11846         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11847         /* now some housekeeping stuff */
11848         if (aop) {
11849           /* we had to allocate for this iCode */
11850           pic16_freeAsmop(NULL,aop,ic,TRUE);
11851         } else { 
11852           /* we did not allocate which means left
11853            * already in a pointer register, then
11854            * if size > 0 && this could be used again
11855            * we have to point it back to where it 
11856            * belongs */
11857           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11858           if (AOP_SIZE(right) > 1
11859             && !OP_SYMBOL(result)->remat
11860             && ( OP_SYMBOL(result)->liveTo > ic->seq
11861             || ic->depth )) {
11862
11863               int size = AOP_SIZE(right) - 1;
11864
11865                 while (size--)
11866                   pic16_emitcode("decf","fsr0,f");
11867                   //pic16_emitcode("dec","%s",rname);
11868             }
11869         }
11870
11871     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11872     /* done */
11873 //release:
11874     pic16_freeAsmop(right,NULL,ic,TRUE);
11875     pic16_freeAsmop(result,NULL,ic,TRUE);
11876 }
11877
11878 /*-----------------------------------------------------------------*/
11879 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11880 /*-----------------------------------------------------------------*/
11881 static void genPagedPointerSet (operand *right,
11882                                operand *result, 
11883                                iCode *ic)
11884 {
11885     asmop *aop = NULL;
11886     regs *preg = NULL ;
11887     char *rname , *l;
11888     sym_link *retype;
11889        
11890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11891
11892     retype= getSpec(operandType(right));
11893     
11894     pic16_aopOp(result,ic,FALSE);
11895     
11896     /* if the value is already in a pointer register
11897        then don't need anything more */
11898     if (!AOP_INPREG(AOP(result))) {
11899         /* otherwise get a free pointer register */
11900         aop = newAsmop(0);
11901         preg = getFreePtr(ic,&aop,FALSE);
11902         pic16_emitcode("mov","%s,%s",
11903                 preg->name,
11904                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11905         rname = preg->name ;
11906     } else
11907         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11908     
11909     pic16_freeAsmop(result,NULL,ic,TRUE);
11910     pic16_aopOp (right,ic,FALSE);
11911
11912     /* if bitfield then unpack the bits */
11913     if (IS_BITFIELD(retype)) 
11914         genPackBits (retype,result,right,rname,PPOINTER);
11915     else {
11916         /* we have can just get the values */
11917         int size = AOP_SIZE(right);
11918         int offset = 0 ;        
11919         
11920         while (size--) {
11921             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11922             
11923             MOVA(l);
11924             pic16_emitcode("movx","@%s,a",rname);
11925
11926             if (size)
11927                 pic16_emitcode("inc","%s",rname);
11928
11929             offset++;
11930         }
11931     }
11932     
11933     /* now some housekeeping stuff */
11934     if (aop) {
11935         /* we had to allocate for this iCode */
11936         pic16_freeAsmop(NULL,aop,ic,TRUE);
11937     } else { 
11938         /* we did not allocate which means left
11939            already in a pointer register, then
11940            if size > 0 && this could be used again
11941            we have to point it back to where it 
11942            belongs */
11943         if (AOP_SIZE(right) > 1 &&
11944             !OP_SYMBOL(result)->remat &&
11945             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11946               ic->depth )) {
11947             int size = AOP_SIZE(right) - 1;
11948             while (size--)
11949                 pic16_emitcode("dec","%s",rname);
11950         }
11951     }
11952
11953     /* done */
11954     pic16_freeAsmop(right,NULL,ic,TRUE);
11955     
11956         
11957 }
11958
11959 /*-----------------------------------------------------------------*/
11960 /* genFarPointerSet - set value from far space                     */
11961 /*-----------------------------------------------------------------*/
11962 static void genFarPointerSet (operand *right,
11963                               operand *result, iCode *ic)
11964 {
11965     int size, offset ;
11966     sym_link *retype = getSpec(operandType(right));
11967
11968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11969     pic16_aopOp(result,ic,FALSE);
11970
11971     /* if the operand is already in dptr 
11972     then we do nothing else we move the value to dptr */
11973     if (AOP_TYPE(result) != AOP_STR) {
11974         /* if this is remateriazable */
11975         if (AOP_TYPE(result) == AOP_IMMD)
11976             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11977         else { /* we need to get it byte by byte */
11978             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11979             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11980             if (options.model == MODEL_FLAT24)
11981             {
11982                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11983             }
11984         }
11985     }
11986     /* so dptr know contains the address */
11987     pic16_freeAsmop(result,NULL,ic,TRUE);
11988     pic16_aopOp(right,ic,FALSE);
11989
11990     /* if bit then unpack */
11991     if (IS_BITFIELD(retype)) 
11992         genPackBits(retype,result,right,"dptr",FPOINTER);
11993     else {
11994         size = AOP_SIZE(right);
11995         offset = 0 ;
11996
11997         while (size--) {
11998             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11999             MOVA(l);
12000             pic16_emitcode("movx","@dptr,a");
12001             if (size)
12002                 pic16_emitcode("inc","dptr");
12003         }
12004     }
12005
12006     pic16_freeAsmop(right,NULL,ic,TRUE);
12007 }
12008
12009 /*-----------------------------------------------------------------*/
12010 /* genGenPointerSet - set value from generic pointer space         */
12011 /*-----------------------------------------------------------------*/
12012 #if 0
12013 static void genGenPointerSet (operand *right,
12014                               operand *result, iCode *ic)
12015 {
12016         int i, size, offset, lit;
12017         sym_link *retype = getSpec(operandType(right));
12018
12019         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12020
12021         pic16_aopOp(result,ic,FALSE);
12022         pic16_aopOp(right,ic,FALSE);
12023         size = AOP_SIZE(right);
12024         offset = 0;
12025
12026         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12027
12028         /* if the operand is already in dptr 
12029                 then we do nothing else we move the value to dptr */
12030         if (AOP_TYPE(result) != AOP_STR) {
12031                 /* if this is remateriazable */
12032                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12033                 // WARNING: anythig until "else" is untested!
12034                 if (AOP_TYPE(result) == AOP_IMMD) {
12035                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12036                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12037                         // load FSR0 from immediate
12038                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12039                         offset = 0;
12040                         while(size--) {
12041                                 if(size) {
12042                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12043                                 } else {
12044                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12045                                 }
12046                                 offset++;
12047                         }
12048                         goto release;
12049                 }
12050                 else { /* we need to get it byte by byte */
12051                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12052                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12053
12054                         // set up FSR0 with address of result
12055                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12056                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12057
12058                         /* hack hack! see if this the FSR. If so don't load W */
12059                         if(AOP_TYPE(right) != AOP_ACC) {
12060
12061                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12062
12063                                 if(AOP_TYPE(right) == AOP_LIT)
12064                                 {
12065                                         // copy literal
12066                                         // note: pic16_popGet handles sign extension
12067                                         for(i=0;i<size;i++) {
12068                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12069                                                 if(i < size-1)
12070                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12071                                                 else
12072                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12073                                         }
12074                                 } else {
12075                                         // copy regs
12076
12077                                         for(i=0;i<size;i++) {
12078                                                 if(i < size-1)
12079                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12080                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12081                                                 else
12082                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12083                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12084                                         }
12085                                 }
12086                                 goto release;
12087                         } 
12088                         // right = ACC
12089                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12090                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12091                         goto release;
12092         } // if (AOP_TYPE(result) != AOP_IMMD)
12093
12094         } // if (AOP_TYPE(result) != AOP_STR)
12095         /* so dptr know contains the address */
12096
12097
12098         /* if bit then unpack */
12099         if (IS_BITFIELD(retype)) 
12100                 genPackBits(retype,result,right,"dptr",GPOINTER);
12101         else {
12102                 size = AOP_SIZE(right);
12103                 offset = 0 ;
12104
12105                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12106
12107                 // set up FSR0 with address of result
12108                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12109                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12110         
12111                 while (size--) {
12112                         if (AOP_TYPE(right) == AOP_LIT) {
12113                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12114                                 if (size) {
12115                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12116                                 } else {
12117                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12118                                 }
12119                         } else { // no literal
12120                                 if(size) {
12121                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12122                                 } else {
12123                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12124                                 }
12125                         }
12126                         offset++;
12127                 }
12128         }
12129
12130         release:
12131         pic16_freeAsmop(right,NULL,ic,TRUE);
12132         pic16_freeAsmop(result,NULL,ic,TRUE);
12133 }
12134 #endif
12135
12136 static void genGenPointerSet (operand *right,
12137                               operand *result, iCode *ic)
12138 {
12139   int size;
12140   sym_link *retype = getSpec(operandType(right));
12141   char fgptrput[32];
12142
12143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12144
12145     pic16_aopOp(result,ic,FALSE);
12146     pic16_aopOp(right,ic,FALSE);
12147     size = AOP_SIZE(right);
12148
12149     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12150
12151
12152     /* if bit then unpack */
12153     if (IS_BITFIELD(retype)) {
12154 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12155       genPackBits(retype,result,right,"dptr",GPOINTER);
12156       goto release;
12157     }
12158
12159     size = AOP_SIZE(right);
12160
12161     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12162
12163
12164
12165     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12166
12167     /* value of right+0 is placed on stack, which will be retrieved
12168      * by the support function this restoring the stack. The important
12169      * thing is that there is no need to manually restore stack pointer
12170      * here */
12171     pushaop(AOP(right), 0);
12172 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12173     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12174     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12175     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12176     
12177     /* load address to write to in WREG:FSR0H:FSR0L */
12178     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12179                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12180     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12181                                 pic16_popCopyReg(&pic16_pc_prodl)));
12182     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12183     
12184
12185     /* put code here */
12186     switch (size) {
12187       case 1: strcpy(fgptrput, "__gptrput1"); break;
12188       case 2: strcpy(fgptrput, "__gptrput2"); break;
12189       case 3: strcpy(fgptrput, "__gptrput3"); break;
12190       case 4: strcpy(fgptrput, "__gptrput4"); break;
12191       default:
12192         werror(W_POSSBUG2, __FILE__, __LINE__);
12193         abort();
12194     }
12195     
12196     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12197     
12198     {
12199       symbol *sym;
12200                   
12201         sym = newSymbol( fgptrput, 0 );
12202         sym->used++;
12203         strcpy(sym->rname, fgptrput);
12204         checkAddSym(&externs, sym);
12205     }
12206
12207 release:
12208     pic16_freeAsmop(right,NULL,ic,TRUE);
12209     pic16_freeAsmop(result,NULL,ic,TRUE);
12210 }
12211
12212 /*-----------------------------------------------------------------*/
12213 /* genPointerSet - stores the value into a pointer location        */
12214 /*-----------------------------------------------------------------*/
12215 static void genPointerSet (iCode *ic)
12216 {    
12217   operand *right, *result ;
12218   sym_link *type, *etype;
12219   int p_type;
12220
12221     FENTRY;
12222
12223     right = IC_RIGHT(ic);
12224     result = IC_RESULT(ic) ;
12225
12226     /* depending on the type of pointer we need to
12227     move it to the correct pointer register */
12228     type = operandType(result);
12229     etype = getSpec(type);
12230     /* if left is of type of pointer then it is simple */
12231     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12232         p_type = DCL_TYPE(type);
12233     }
12234     else {
12235         /* we have to go by the storage class */
12236         p_type = PTR_TYPE(SPEC_OCLS(etype));
12237
12238 /*      if (SPEC_OCLS(etype)->codesp ) { */
12239 /*          p_type = CPOINTER ;  */
12240 /*      } */
12241 /*      else */
12242 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12243 /*              p_type = FPOINTER ; */
12244 /*          else */
12245 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12246 /*                  p_type = PPOINTER ; */
12247 /*              else */
12248 /*                  if (SPEC_OCLS(etype) == idata ) */
12249 /*                      p_type = IPOINTER ; */
12250 /*                  else */
12251 /*                      p_type = POINTER ; */
12252     }
12253
12254     /* now that we have the pointer type we assign
12255     the pointer values */
12256     switch (p_type) {
12257       case POINTER:
12258       case IPOINTER:
12259         genNearPointerSet (right,result,ic);
12260         break;
12261
12262       case PPOINTER:
12263         genPagedPointerSet (right,result,ic);
12264         break;
12265
12266       case FPOINTER:
12267         genFarPointerSet (right,result,ic);
12268         break;
12269         
12270       case GPOINTER:
12271         genGenPointerSet (right,result,ic);
12272         break;
12273
12274       default:
12275         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12276           "genPointerSet: illegal pointer type");
12277     }
12278 }
12279
12280 /*-----------------------------------------------------------------*/
12281 /* genIfx - generate code for Ifx statement                        */
12282 /*-----------------------------------------------------------------*/
12283 static void genIfx (iCode *ic, iCode *popIc)
12284 {
12285   operand *cond = IC_COND(ic);
12286   int isbit =0;
12287
12288     FENTRY;
12289
12290     pic16_aopOp(cond,ic,FALSE);
12291
12292     /* get the value into acc */
12293     if (AOP_TYPE(cond) != AOP_CRY)
12294       pic16_toBoolean(cond);
12295     else
12296       isbit = 1;
12297     /* the result is now in the accumulator */
12298     pic16_freeAsmop(cond,NULL,ic,TRUE);
12299
12300     /* if there was something to be popped then do it */
12301     if (popIc)
12302       genIpop(popIc);
12303
12304     /* if the condition is  a bit variable */
12305     if (isbit && IS_ITEMP(cond) && 
12306         SPIL_LOC(cond)) {
12307       genIfxJump(ic,"c");
12308       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12309     } else {
12310       if (isbit && !IS_ITEMP(cond))
12311         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12312         else
12313         genIfxJump(ic,"a");
12314     }
12315     ic->generated = 1;
12316 }
12317
12318 /*-----------------------------------------------------------------*/
12319 /* genAddrOf - generates code for address of                       */
12320 /*-----------------------------------------------------------------*/
12321 static void genAddrOf (iCode *ic)
12322 {
12323   operand *result, *left;
12324   int size;
12325   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12326   pCodeOp *pcop0, *pcop1, *pcop2;
12327
12328     FENTRY;
12329
12330     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12331
12332     sym = OP_SYMBOL( IC_LEFT(ic) );
12333     
12334     if(sym->onStack) {
12335       /* get address of symbol on stack */
12336       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12337 #if 0
12338       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12339                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12340 #endif
12341
12342       // operands on stack are accessible via "FSR2 + index" with index
12343       // starting at 2 for arguments and growing from 0 downwards for
12344       // local variables (index == 0 is not assigned so we add one here)
12345       {
12346         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12347         if (soffs <= 0) {
12348           assert (soffs < 0);
12349           soffs++;
12350         } // if
12351         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12352         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12353         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12354         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12355         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12356         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12357         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12358       }
12359
12360       goto release;
12361     }
12362         
12363 //      if(pic16_debug_verbose) {
12364 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12365 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12366 //      }
12367         
12368     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12369     size = AOP_SIZE(IC_RESULT(ic));
12370
12371     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12372     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12373     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12374         
12375     if (size == 3) {
12376       pic16_emitpcode(POC_MOVLW, pcop0);
12377       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12378       pic16_emitpcode(POC_MOVLW, pcop1);
12379       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12380       pic16_emitpcode(POC_MOVLW, pcop2);
12381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12382     } else
12383     if (size == 2) {
12384       pic16_emitpcode(POC_MOVLW, pcop0);
12385       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12386       pic16_emitpcode(POC_MOVLW, pcop1);
12387     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12388     } else {
12389       pic16_emitpcode(POC_MOVLW, pcop0);
12390       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12391     }
12392
12393     pic16_freeAsmop(left, NULL, ic, FALSE);
12394 release:
12395     pic16_freeAsmop(result,NULL,ic,TRUE);
12396 }
12397
12398
12399 #if 0
12400 /*-----------------------------------------------------------------*/
12401 /* genFarFarAssign - assignment when both are in far space         */
12402 /*-----------------------------------------------------------------*/
12403 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12404 {
12405     int size = AOP_SIZE(right);
12406     int offset = 0;
12407     char *l ;
12408     /* first push the right side on to the stack */
12409     while (size--) {
12410         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12411         MOVA(l);
12412         pic16_emitcode ("push","acc");
12413     }
12414     
12415     pic16_freeAsmop(right,NULL,ic,FALSE);
12416     /* now assign DPTR to result */
12417     pic16_aopOp(result,ic,FALSE);
12418     size = AOP_SIZE(result);
12419     while (size--) {
12420         pic16_emitcode ("pop","acc");
12421         pic16_aopPut(AOP(result),"a",--offset);
12422     }
12423     pic16_freeAsmop(result,NULL,ic,FALSE);
12424         
12425 }
12426 #endif
12427
12428 /*-----------------------------------------------------------------*/
12429 /* genAssign - generate code for assignment                        */
12430 /*-----------------------------------------------------------------*/
12431 static void genAssign (iCode *ic)
12432 {
12433   operand *result, *right;
12434   int size, offset,know_W;
12435   unsigned long lit = 0L;
12436
12437   result = IC_RESULT(ic);
12438   right  = IC_RIGHT(ic) ;
12439
12440   FENTRY;
12441   
12442   /* if they are the same */
12443   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12444     return ;
12445
12446   /* reversed order operands are aopOp'ed so that result operand
12447    * is effective in case right is a stack symbol. This maneauver
12448    * allows to use the _G.resDirect flag later */
12449   pic16_aopOp(result,ic,TRUE);
12450   pic16_aopOp(right,ic,FALSE);
12451
12452   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12453
12454   /* if they are the same registers */
12455   if (pic16_sameRegs(AOP(right),AOP(result)))
12456     goto release;
12457
12458   /* if the result is a bit */
12459   if (AOP_TYPE(result) == AOP_CRY) {
12460     /* if the right size is a literal then
12461        we know what the value is */
12462     if (AOP_TYPE(right) == AOP_LIT) {
12463           
12464       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12465                   pic16_popGet(AOP(result),0));
12466
12467       if (((int) operandLitValue(right))) 
12468         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12469                        AOP(result)->aopu.aop_dir,
12470                        AOP(result)->aopu.aop_dir);
12471       else
12472         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12473                        AOP(result)->aopu.aop_dir,
12474                        AOP(result)->aopu.aop_dir);
12475       goto release;
12476     }
12477
12478     /* the right is also a bit variable */
12479     if (AOP_TYPE(right) == AOP_CRY) {
12480       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12481       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12482       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12483
12484       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12485                      AOP(result)->aopu.aop_dir,
12486                      AOP(result)->aopu.aop_dir);
12487       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12488                      AOP(right)->aopu.aop_dir,
12489                      AOP(right)->aopu.aop_dir);
12490       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12491                      AOP(result)->aopu.aop_dir,
12492                      AOP(result)->aopu.aop_dir);
12493       goto release ;
12494     }
12495
12496     /* we need to or */
12497     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12498     pic16_toBoolean(right);
12499     emitSKPZ;
12500     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12501     //pic16_aopPut(AOP(result),"a",0);
12502     goto release ;
12503   }
12504
12505   /* bit variables done */
12506   /* general case */
12507   size = AOP_SIZE(result);
12508   offset = 0 ;
12509
12510   if(AOP_TYPE(right) == AOP_LIT) {
12511         if(!IS_FLOAT(operandType( right )))
12512                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12513         else {
12514            union {
12515               unsigned long lit_int;
12516               float lit_float;
12517             } info;
12518         
12519                 /* take care if literal is a float */
12520                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12521                 lit = info.lit_int;
12522         }
12523   }
12524
12525 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12526 //                      sizeof(unsigned long int), sizeof(float));
12527
12528
12529   if (AOP_TYPE(right) == AOP_REG) {
12530     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12531     while (size--) {
12532       
12533       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12534     } // while
12535     goto release;
12536   }
12537
12538   if(AOP_TYPE(right) != AOP_LIT
12539         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12540         && !IS_FUNC(OP_SYM_TYPE(right))
12541         ) {
12542         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12543         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12544
12545         // set up table pointer
12546         if(is_LitOp(right)) {
12547 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12548                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12549                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12550                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12551                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12552                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12553                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12554         } else {
12555 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12556                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12557                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12558                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12559                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12560                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12561                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12562         }
12563
12564         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12565         while(size--) {
12566                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12567                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12568                         pic16_popGet(AOP(result),offset)));
12569                 offset++;
12570         }
12571
12572         size = getSize(OP_SYM_ETYPE(right));
12573         if(AOP_SIZE(result) > size) {
12574                 size = AOP_SIZE(result) - size;
12575                 while(size--) {
12576                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12577                         offset++;
12578                 }
12579         }
12580         goto release;
12581   }
12582
12583
12584
12585 #if 0
12586 /* VR - What is this?! */
12587   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12588     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12589     if(aopIdx(AOP(result),0) == 4) {
12590
12591       /* this is a workaround to save value of right into wreg too,
12592        * value of wreg is going to be used later */
12593       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12594       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12595       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12596       goto release;
12597     } else
12598 //      assert(0);
12599       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12600   }
12601 #endif
12602
12603   know_W=-1;
12604   while (size--) {
12605   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12606     if(AOP_TYPE(right) == AOP_LIT) {
12607       if(lit&0xff) {
12608         if(know_W != (lit&0xff))
12609           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12610         know_W = lit&0xff;
12611         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12612       } else
12613         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12614
12615       lit >>= 8;
12616
12617     } else if (AOP_TYPE(right) == AOP_CRY) {
12618       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12619       if(offset == 0) {
12620         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12621         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12622         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12623       }
12624     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12625         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12626         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12627     } else {
12628       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12629
12630       if(!_G.resDirect)         /* use this aopForSym feature */
12631         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12632     }
12633             
12634     offset++;
12635   }
12636   
12637  release:
12638   pic16_freeAsmop (right,NULL,ic,FALSE);
12639   pic16_freeAsmop (result,NULL,ic,TRUE);
12640 }   
12641
12642 /*-----------------------------------------------------------------*/
12643 /* genJumpTab - generates code for jump table                       */
12644 /*-----------------------------------------------------------------*/
12645 static void genJumpTab (iCode *ic)
12646 {
12647   symbol *jtab;
12648   char *l;
12649   pCodeOp *jt_offs;
12650   pCodeOp *jt_offs_hi;
12651   pCodeOp *jt_label;
12652
12653     FENTRY;
12654
12655     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12656     /* get the condition into accumulator */
12657     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12658     MOVA(l);
12659     /* multiply by three */
12660     pic16_emitcode("add","a,acc");
12661     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12662
12663     jtab = newiTempLabel(NULL);
12664     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12665     pic16_emitcode("jmp","@a+dptr");
12666     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12667
12668 #if 0
12669     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12670     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12671     emitSKPNC;
12672     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12673     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12674     pic16_emitpLabel(jtab->key);
12675
12676 #else
12677
12678     jt_offs = pic16_popGetTempReg(0);
12679     jt_offs_hi = pic16_popGetTempReg(1);
12680     jt_label = pic16_popGetLabel (jtab->key);
12681     //fprintf (stderr, "Creating jump table...\n");
12682
12683     // calculate offset into jump table (idx * sizeof (GOTO))
12684     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12685     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12686     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12687     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12688     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12689     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12690     pic16_emitpcode(POC_MOVWF , jt_offs);
12691
12692     // prepare PCLATx (set to first entry in jump table)
12693     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12694     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12695     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12696     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12697     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12698
12699     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12700     pic16_emitpcode(POC_ADDWF , jt_offs);
12701     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12702     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12703     emitSKPNC;
12704     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12705
12706     // release temporaries and prepare jump into table (new PCL --> WREG)
12707     pic16_emitpcode(POC_MOVFW , jt_offs);
12708     pic16_popReleaseTempReg (jt_offs_hi, 1);
12709     pic16_popReleaseTempReg (jt_offs, 0);
12710
12711     // jump into the table
12712     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12713
12714     pic16_emitpLabelFORCE(jtab->key);
12715 #endif
12716
12717     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12718 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12719
12720     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12721     /* now generate the jump labels */
12722     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12723          jtab = setNextItem(IC_JTLABELS(ic))) {
12724 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12725         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12726         
12727     }
12728     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12729
12730 }
12731
12732 /*-----------------------------------------------------------------*/
12733 /* genMixedOperation - gen code for operators between mixed types  */
12734 /*-----------------------------------------------------------------*/
12735 /*
12736   TSD - Written for the PIC port - but this unfortunately is buggy.
12737   This routine is good in that it is able to efficiently promote 
12738   types to different (larger) sizes. Unfortunately, the temporary
12739   variables that are optimized out by this routine are sometimes
12740   used in other places. So until I know how to really parse the 
12741   iCode tree, I'm going to not be using this routine :(.
12742 */
12743 static int genMixedOperation (iCode *ic)
12744 {
12745 #if 0
12746   operand *result = IC_RESULT(ic);
12747   sym_link *ctype = operandType(IC_LEFT(ic));
12748   operand *right = IC_RIGHT(ic);
12749   int ret = 0;
12750   int big,small;
12751   int offset;
12752
12753   iCode *nextic;
12754   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12755
12756   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12757
12758   nextic = ic->next;
12759   if(!nextic)
12760     return 0;
12761
12762   nextright = IC_RIGHT(nextic);
12763   nextleft  = IC_LEFT(nextic);
12764   nextresult = IC_RESULT(nextic);
12765
12766   pic16_aopOp(right,ic,FALSE);
12767   pic16_aopOp(result,ic,FALSE);
12768   pic16_aopOp(nextright,  nextic, FALSE);
12769   pic16_aopOp(nextleft,   nextic, FALSE);
12770   pic16_aopOp(nextresult, nextic, FALSE);
12771
12772   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12773
12774     operand *t = right;
12775     right = nextright;
12776     nextright = t; 
12777
12778     pic16_emitcode(";remove right +","");
12779
12780   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12781 /*
12782     operand *t = right;
12783     right = nextleft;
12784     nextleft = t; 
12785 */
12786     pic16_emitcode(";remove left +","");
12787   } else
12788     return 0;
12789
12790   big = AOP_SIZE(nextleft);
12791   small = AOP_SIZE(nextright);
12792
12793   switch(nextic->op) {
12794
12795   case '+':
12796     pic16_emitcode(";optimize a +","");
12797     /* if unsigned or not an integral type */
12798     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12799       pic16_emitcode(";add a bit to something","");
12800     } else {
12801
12802       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12803
12804       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12805         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12806         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12807       } else
12808         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12809
12810       offset = 0;
12811       while(--big) {
12812
12813         offset++;
12814
12815         if(--small) {
12816           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12817             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12818             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12819           }
12820
12821           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12822           emitSKPNC;
12823           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12824                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12825                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12826           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12827           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12828
12829         } else {
12830           pic16_emitcode("rlf","known_zero,w");
12831
12832           /*
12833             if right is signed
12834               btfsc  right,7
12835                addlw ff
12836           */
12837           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12838             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12839             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12840           } else {
12841             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12842           }
12843         }
12844       }
12845       ret = 1;
12846     }
12847   }
12848   ret = 1;
12849
12850 release:
12851   pic16_freeAsmop(right,NULL,ic,TRUE);
12852   pic16_freeAsmop(result,NULL,ic,TRUE);
12853   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12854   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12855   if(ret)
12856     nextic->generated = 1;
12857
12858   return ret;
12859 #else
12860   return 0;
12861 #endif
12862 }
12863 /*-----------------------------------------------------------------*/
12864 /* genCast - gen code for casting                                  */
12865 /*-----------------------------------------------------------------*/
12866 static void genCast (iCode *ic)
12867 {
12868   operand *result = IC_RESULT(ic);
12869   sym_link *ctype = operandType(IC_LEFT(ic));
12870   sym_link *rtype = operandType(IC_RIGHT(ic));
12871   sym_link *restype = operandType(IC_RESULT(ic));
12872   operand *right = IC_RIGHT(ic);
12873   int size, offset ;
12874
12875
12876     FENTRY;
12877
12878         /* if they are equivalent then do nothing */
12879 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12880 //              return ;
12881
12882         pic16_aopOp(result,ic,FALSE);
12883         pic16_aopOp(right,ic,FALSE) ;
12884
12885         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12886
12887
12888         /* if the result is a bit */
12889         if (AOP_TYPE(result) == AOP_CRY) {
12890         
12891                 /* if the right size is a literal then
12892                  * we know what the value is */
12893                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12894
12895                 if (AOP_TYPE(right) == AOP_LIT) {
12896                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12897                                 pic16_popGet(AOP(result),0));
12898
12899                         if (((int) operandLitValue(right))) 
12900                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12901                                         AOP(result)->aopu.aop_dir,
12902                                         AOP(result)->aopu.aop_dir);
12903                         else
12904                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12905                                         AOP(result)->aopu.aop_dir,
12906                                         AOP(result)->aopu.aop_dir);
12907                         goto release;
12908                 }
12909
12910                 /* the right is also a bit variable */
12911                 if (AOP_TYPE(right) == AOP_CRY) {
12912                         emitCLRC;
12913                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12914
12915                         pic16_emitcode("clrc","");
12916                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12917                                 AOP(right)->aopu.aop_dir,
12918                                 AOP(right)->aopu.aop_dir);
12919                         pic16_aopPut(AOP(result),"c",0);
12920                         goto release ;
12921                 }
12922
12923                 /* we need to or */
12924                 if (AOP_TYPE(right) == AOP_REG) {
12925                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12926                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12927                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12928                 }
12929                 pic16_toBoolean(right);
12930                 pic16_aopPut(AOP(result),"a",0);
12931                 goto release ;
12932         }
12933
12934         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12935           int offset = 1;
12936
12937                 size = AOP_SIZE(result);
12938
12939                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12940
12941                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12942                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12943                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12944
12945                 while (size--)
12946                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12947
12948                 goto release;
12949         }
12950
12951         if(IS_BITFIELD(getSpec(restype))
12952           && IS_BITFIELD(getSpec(rtype))) {
12953           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12954         }
12955
12956         /* if they are the same size : or less */
12957         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12958
12959                 /* if they are in the same place */
12960                 if (pic16_sameRegs(AOP(right),AOP(result)))
12961                         goto release;
12962
12963                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12964 #if 0
12965                 if (IS_PTR_CONST(rtype))
12966 #else
12967                 if (IS_CODEPTR(rtype))
12968 #endif
12969                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12970
12971 #if 0
12972                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12973 #else
12974                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12975 #endif
12976                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12977
12978 #if 0
12979                 if(AOP_TYPE(right) == AOP_IMMD) {
12980                   pCodeOp *pcop0, *pcop1, *pcop2;
12981                   symbol *sym = OP_SYMBOL( right );
12982
12983                         size = AOP_SIZE(result);
12984                         /* low */
12985                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12986                         /* high */
12987                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12988                         /* upper */
12989                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12990         
12991                         if (size == 3) {
12992                                 pic16_emitpcode(POC_MOVLW, pcop0);
12993                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12994                                 pic16_emitpcode(POC_MOVLW, pcop1);
12995                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12996                                 pic16_emitpcode(POC_MOVLW, pcop2);
12997                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12998                         } else
12999                         if (size == 2) {
13000                                 pic16_emitpcode(POC_MOVLW, pcop0);
13001                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13002                                 pic16_emitpcode(POC_MOVLW, pcop1);
13003                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13004                         } else {
13005                                 pic16_emitpcode(POC_MOVLW, pcop0);
13006                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13007                         }
13008                 } else
13009 #endif
13010                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13011                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13012                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13013                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13014                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13015                         if(AOP_SIZE(result) <2)
13016                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13017                 } else {
13018                         /* if they in different places then copy */
13019                         size = AOP_SIZE(result);
13020                         offset = 0 ;
13021                         while (size--) {
13022                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13023                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13024                                 offset++;
13025                         }
13026                 }
13027                 goto release;
13028         }
13029
13030         /* if the result is of type pointer */
13031         if (IS_PTR(ctype)) {
13032           int p_type;
13033           sym_link *type = operandType(right);
13034           sym_link *etype = getSpec(type);
13035
13036                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13037
13038                 /* pointer to generic pointer */
13039                 if (IS_GENPTR(ctype)) {
13040                   char *l = zero;
13041             
13042                         if (IS_PTR(type)) 
13043                                 p_type = DCL_TYPE(type);
13044                         else {
13045                 /* we have to go by the storage class */
13046                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13047
13048 /*              if (SPEC_OCLS(etype)->codesp )  */
13049 /*                  p_type = CPOINTER ;  */
13050 /*              else */
13051 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13052 /*                      p_type = FPOINTER ; */
13053 /*                  else */
13054 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13055 /*                          p_type = PPOINTER; */
13056 /*                      else */
13057 /*                          if (SPEC_OCLS(etype) == idata ) */
13058 /*                              p_type = IPOINTER ; */
13059 /*                          else */
13060 /*                              p_type = POINTER ; */
13061             }
13062                 
13063             /* the first two bytes are known */
13064       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13065             size = GPTRSIZE - 1; 
13066             offset = 0 ;
13067             while (size--) {
13068               if(offset < AOP_SIZE(right)) {
13069                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13070                 mov2f(AOP(result), AOP(right), offset);
13071 /*
13072                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13073                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13074                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13075                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13076                 } else { 
13077                   
13078                   pic16_aopPut(AOP(result),
13079                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13080                          offset);
13081                 }
13082 */
13083               } else 
13084                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13085               offset++;
13086             }
13087             /* the last byte depending on type */
13088             switch (p_type) {
13089             case IPOINTER:
13090             case POINTER:
13091                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13092                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13093 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13094                 break;
13095
13096             case CPOINTER:
13097                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13098                 break;
13099
13100             case FPOINTER:
13101               pic16_emitcode(";BUG!? ","%d",__LINE__);
13102                 l = one;
13103                 break;
13104             case PPOINTER:
13105               pic16_emitcode(";BUG!? ","%d",__LINE__);
13106                 l = "#0x03";
13107                 break;
13108
13109             case GPOINTER:
13110                 if (GPTRSIZE > AOP_SIZE(right)) {
13111                   // assume data pointer... THIS MIGHT BE WRONG!
13112                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13113                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13114                 } else {
13115                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13116                 }
13117               break;
13118               
13119             default:
13120                 /* this should never happen */
13121                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13122                        "got unknown pointer type");
13123                 exit(1);
13124             }
13125             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13126             goto release ;
13127         }
13128         
13129         
13130         assert( 0 );
13131         /* just copy the pointers */
13132         size = AOP_SIZE(result);
13133         offset = 0 ;
13134         while (size--) {
13135             pic16_aopPut(AOP(result),
13136                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13137                    offset);
13138             offset++;
13139         }
13140         goto release ;
13141     }
13142     
13143
13144
13145     /* so we now know that the size of destination is greater
13146     than the size of the source.
13147     Now, if the next iCode is an operator then we might be
13148     able to optimize the operation without performing a cast.
13149     */
13150     if(genMixedOperation(ic))
13151       goto release;
13152
13153     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13154     
13155     /* we move to result for the size of source */
13156     size = AOP_SIZE(right);
13157     offset = 0 ;
13158
13159     while (size--) {
13160       if(!_G.resDirect)
13161         mov2f(AOP(result), AOP(right), offset);
13162       offset++;
13163     }
13164
13165     /* now depending on the sign of the destination */
13166     size = AOP_SIZE(result) - AOP_SIZE(right);
13167     /* if unsigned or not an integral type */
13168     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13169       while (size--)
13170         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13171     } else {
13172       /* we need to extend the sign :( */
13173
13174       if(size == 1) {
13175         /* Save one instruction of casting char to int */
13176         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13177         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13178         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13179       } else {
13180         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13181
13182         if(offset)
13183           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13184         else
13185           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13186         
13187         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13188
13189         while (size--)
13190           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13191       }
13192     }
13193
13194 release:
13195     pic16_freeAsmop(right,NULL,ic,TRUE);
13196     pic16_freeAsmop(result,NULL,ic,TRUE);
13197
13198 }
13199
13200 /*-----------------------------------------------------------------*/
13201 /* genDjnz - generate decrement & jump if not zero instrucion      */
13202 /*-----------------------------------------------------------------*/
13203 static int genDjnz (iCode *ic, iCode *ifx)
13204 {
13205     symbol *lbl, *lbl1;
13206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13207
13208     if (!ifx)
13209         return 0;
13210     
13211     /* if the if condition has a false label
13212        then we cannot save */
13213     if (IC_FALSE(ifx))
13214         return 0;
13215
13216     /* if the minus is not of the form 
13217        a = a - 1 */
13218     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13219         !IS_OP_LITERAL(IC_RIGHT(ic)))
13220         return 0;
13221
13222     if (operandLitValue(IC_RIGHT(ic)) != 1)
13223         return 0;
13224
13225     /* if the size of this greater than one then no
13226        saving */
13227     if (getSize(operandType(IC_RESULT(ic))) > 1)
13228         return 0;
13229
13230     /* otherwise we can save BIG */
13231     lbl = newiTempLabel(NULL);
13232     lbl1= newiTempLabel(NULL);
13233
13234     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13235     
13236     if (IS_AOP_PREG(IC_RESULT(ic))) {
13237         pic16_emitcode("dec","%s",
13238                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13239         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13240         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13241     } else {    
13242
13243
13244       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13245       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13246
13247       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13248       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13249
13250     }
13251     
13252     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13253     ifx->generated = 1;
13254     return 1;
13255 }
13256
13257 /*-----------------------------------------------------------------*/
13258 /* genReceive - generate code for a receive iCode                  */
13259 /*-----------------------------------------------------------------*/
13260 static void genReceive (iCode *ic)
13261 {    
13262
13263   FENTRY;
13264
13265 #if 0
13266   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13267         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13268 #endif
13269 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13270
13271   if (isOperandInFarSpace(IC_RESULT(ic))
13272       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13273           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13274
13275     int size = getSize(operandType(IC_RESULT(ic)));
13276     int offset =  pic16_fReturnSizePic - size;
13277
13278       assert( 0 );
13279       while (size--) {
13280         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13281                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13282                       offset++;
13283         }
13284
13285       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13286
13287       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13288       size = AOP_SIZE(IC_RESULT(ic));
13289       offset = 0;
13290       while (size--) {
13291         pic16_emitcode ("pop","acc");
13292         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13293       }
13294   } else {
13295     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13296     _G.accInUse++;
13297     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13298     _G.accInUse--;
13299
13300     /* set pseudo stack pointer to where it should be - dw*/
13301     GpsuedoStkPtr = ic->parmBytes;
13302
13303     /* setting GpsuedoStkPtr has side effects here: */
13304     assignResultValue(IC_RESULT(ic), 0);
13305   }
13306
13307   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13308 }
13309
13310 /*-----------------------------------------------------------------*/
13311 /* genDummyRead - generate code for dummy read of volatiles        */
13312 /*-----------------------------------------------------------------*/
13313 static void
13314 genDummyRead (iCode * ic)
13315 {
13316   operand *op;
13317   int i;
13318
13319   op = IC_RIGHT(ic);
13320   if (op && IS_SYMOP(op)) {
13321     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13322       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13323       return;
13324     }
13325     pic16_aopOp (op, ic, FALSE);
13326     for (i=0; i < AOP_SIZE(op); i++) {
13327       // may need to protect this from the peepholer -- this is not nice but works...
13328       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13329       pic16_mov2w (AOP(op),i);
13330       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13331     } // for i
13332     pic16_freeAsmop (op, NULL, ic, TRUE);
13333   } else if (op) {
13334     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13335   } // if
13336 }
13337
13338 /*-----------------------------------------------------------------*/
13339 /* genpic16Code - generate code for pic16 based controllers        */
13340 /*-----------------------------------------------------------------*/
13341 /*
13342  * At this point, ralloc.c has gone through the iCode and attempted
13343  * to optimize in a way suitable for a PIC. Now we've got to generate
13344  * PIC instructions that correspond to the iCode.
13345  *
13346  * Once the instructions are generated, we'll pass through both the
13347  * peep hole optimizer and the pCode optimizer.
13348  *-----------------------------------------------------------------*/
13349
13350 void genpic16Code (iCode *lic)
13351 {
13352   iCode *ic;
13353   int cln = 0;
13354
13355     lineHead = lineCurr = NULL;
13356
13357     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13358     pic16_addpBlock(pb);
13359
13360 #if 0
13361     /* if debug information required */
13362     if (options.debug && currFunc) {
13363       if (currFunc) {
13364         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13365       }
13366     }
13367 #endif
13368
13369     for (ic = lic ; ic ; ic = ic->next ) {
13370
13371       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13372       if ( cln != ic->lineno ) {
13373         if ( options.debug ) {
13374           debugFile->writeCLine (ic);
13375         }
13376         
13377         if(!options.noCcodeInAsm) {
13378           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13379               printCLine(ic->filename, ic->lineno)));
13380         }
13381
13382         cln = ic->lineno ;
13383       }
13384         
13385       if(options.iCodeInAsm) {
13386         char *l;
13387
13388           /* insert here code to print iCode as comment */
13389           l = Safe_strdup(printILine(ic));
13390           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13391       }
13392         
13393       /* if the result is marked as
13394        * spilt and rematerializable or code for
13395        * this has already been generated then
13396        * do nothing */
13397       if (resultRemat(ic) || ic->generated ) 
13398         continue ;
13399         
13400       /* depending on the operation */
13401       switch (ic->op) {
13402         case '!' :
13403           pic16_genNot(ic);
13404           break;
13405             
13406         case '~' :
13407           pic16_genCpl(ic);
13408           break;
13409             
13410         case UNARYMINUS:
13411           genUminus (ic);
13412           break;
13413             
13414         case IPUSH:
13415           genIpush (ic);
13416           break;
13417             
13418         case IPOP:
13419           /* IPOP happens only when trying to restore a 
13420            * spilt live range, if there is an ifx statement
13421            * following this pop then the if statement might
13422            * be using some of the registers being popped which
13423            * would destroy the contents of the register so
13424            * we need to check for this condition and handle it */
13425            if (ic->next
13426              && ic->next->op == IFX
13427              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13428                genIfx (ic->next,ic);
13429           else
13430             genIpop (ic);
13431           break; 
13432             
13433         case CALL:
13434           genCall (ic);
13435           break;
13436             
13437         case PCALL:
13438           genPcall (ic);
13439           break;
13440             
13441         case FUNCTION:
13442           genFunction (ic);
13443           break;
13444             
13445         case ENDFUNCTION:
13446           genEndFunction (ic);
13447           break;
13448             
13449         case RETURN:
13450           genRet (ic);
13451           break;
13452             
13453         case LABEL:
13454           genLabel (ic);
13455           break;
13456             
13457         case GOTO:
13458           genGoto (ic);
13459           break;
13460             
13461         case '+' :
13462           pic16_genPlus (ic) ;
13463           break;
13464             
13465         case '-' :
13466           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13467             pic16_genMinus (ic);
13468           break;
13469
13470         case '*' :
13471           genMult (ic);
13472           break;
13473             
13474         case '/' :
13475           genDiv (ic) ;
13476           break;
13477             
13478         case '%' :
13479           genMod (ic);
13480           break;
13481             
13482         case '>' :
13483           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13484           break;
13485             
13486         case '<' :
13487           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13488           break;
13489             
13490         case LE_OP:
13491         case GE_OP:
13492         case NE_OP:
13493           /* note these two are xlated by algebraic equivalence
13494            * during parsing SDCC.y */
13495           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13496             "got '>=' or '<=' shouldn't have come here");
13497           break;
13498
13499         case EQ_OP:
13500           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13501           break;            
13502             
13503         case AND_OP:
13504           genAndOp (ic);
13505           break;
13506             
13507         case OR_OP:
13508           genOrOp (ic);
13509           break;
13510             
13511         case '^' :
13512           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13513           break;
13514             
13515         case '|' :
13516           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13517           break;
13518             
13519         case BITWISEAND:
13520           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13521           break;
13522             
13523         case INLINEASM:
13524           genInline (ic);
13525           break;
13526             
13527         case RRC:
13528           genRRC (ic);
13529           break;
13530             
13531         case RLC:
13532           genRLC (ic);
13533           break;
13534             
13535         case GETHBIT:
13536           genGetHbit (ic);
13537           break;
13538             
13539         case LEFT_OP:
13540           genLeftShift (ic);
13541           break;
13542             
13543         case RIGHT_OP:
13544           genRightShift (ic);
13545           break;
13546             
13547         case GET_VALUE_AT_ADDRESS:
13548           genPointerGet(ic);
13549           break;
13550             
13551         case '=' :
13552           if (POINTER_SET(ic))
13553             genPointerSet(ic);
13554           else
13555             genAssign(ic);
13556           break;
13557             
13558         case IFX:
13559           genIfx (ic,NULL);
13560           break;
13561             
13562         case ADDRESS_OF:
13563           genAddrOf (ic);
13564           break;
13565             
13566         case JUMPTABLE:
13567           genJumpTab (ic);
13568           break;
13569             
13570         case CAST:
13571           genCast (ic);
13572           break;
13573             
13574         case RECEIVE:
13575           genReceive(ic);
13576           break;
13577             
13578         case SEND:
13579           addSet(&_G.sendSet,ic);
13580           break;
13581
13582         case DUMMY_READ_VOLATILE:
13583           genDummyRead (ic);
13584           break;
13585
13586         default :
13587           ic = ic;
13588       }
13589     }
13590
13591
13592     /* now we are ready to call the
13593        peep hole optimizer */
13594     if (!options.nopeep)
13595       peepHole (&lineHead);
13596
13597     /* now do the actual printing */
13598     printLine (lineHead, codeOutFile);
13599
13600 #ifdef PCODE_DEBUG
13601     DFPRINTF((stderr,"printing pBlock\n\n"));
13602     pic16_printpBlock(stdout,pb);
13603 #endif
13604
13605     return;
13606 }
13607