* src/pic16/gen.c (pic16_loadFSR0, genPackBits, genUnpackBits,
[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 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
140
141 static char *accUse[] = {"WREG"};
142
143 //static short rbank = -1;
144
145 static struct {
146     short r0Pushed;
147     short r1Pushed;
148     short fsr0Pushed;
149     short accInUse;
150     short inLine;
151     short debugLine;
152     short nRegsSaved;
153     short ipushRegs;
154     set *sendSet;
155     set *stackRegSet;
156     int usefastretfie;
157     bitVect *fregsUsed;
158     int stack_lat;                      /* stack offset latency */
159     int resDirect;
160     int useWreg;                        /* flag when WREG is used to pass function parameter */
161 } _G;
162
163 /* Resolved ifx structure. This structure stores information
164    about an iCode ifx that makes it easier to generate code.
165 */
166 typedef struct resolvedIfx {
167   symbol *lbl;     /* pointer to a label */
168   int condition;   /* true or false ifx */
169   int generated;   /* set true when the code associated with the ifx
170                     * is generated */
171 } resolvedIfx;
172
173 extern int pic16_ptrRegReq ;
174 extern int pic16_nRegs;
175 extern FILE *codeOutFile;
176 //static void saverbank (int, iCode *,bool);
177
178 static lineNode *lineHead = NULL;
179 static lineNode *lineCurr = NULL;
180
181 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
182 0xE0, 0xC0, 0x80, 0x00};
183 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
185
186 static  pBlock *pb;
187
188 /*-----------------------------------------------------------------*/
189 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
190 /*                 exponent of 2 is returned, otherwise -1 is      */
191 /*                 returned.                                       */
192 /* note that this is similar to the function `powof2' in SDCCsymt  */
193 /* if(n == 2^y)                                                    */
194 /*   return y;                                                     */
195 /* return -1;                                                      */
196 /*-----------------------------------------------------------------*/
197 int pic16_my_powof2 (unsigned long num)
198 {
199   if(num) {
200     if( (num & (num-1)) == 0) {
201       int nshifts = -1;
202       while(num) {
203         num>>=1;
204         nshifts++;
205       }
206       return nshifts;
207     }
208   }
209
210   return -1;
211 }
212
213 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
214 {
215   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
216                        line_no,
217                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
218                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
219                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
220                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
221                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
222                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
223                        ((result) ? AOP_SIZE(result) : 0));
224 }
225
226 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
227 {
228
229   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
230                        line_no,
231                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
232                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
233                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
234                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
235                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
236                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
237
238 }
239
240 void pic16_emitpcomment (char *fmt, ...)
241 {
242     va_list ap;
243     char lb[INITIAL_INLINEASM];  
244     char *lbp = lb;
245
246     va_start(ap,fmt);   
247
248     lb[0] = ';';
249     vsprintf(lb+1,fmt,ap);
250
251     while (isspace(*lbp)) lbp++;
252
253     if (lbp && *lbp) 
254         lineCurr = (lineCurr ?
255                     connectLine(lineCurr,newLineNode(lb)) :
256                     (lineHead = newLineNode(lb)));
257     lineCurr->isInline = _G.inLine;
258     lineCurr->isDebug  = _G.debugLine;
259
260     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
261     va_end(ap);
262
263 //      fprintf(stderr, "%s\n", lb);
264 }
265
266 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
267 {
268     va_list ap;
269     char lb[INITIAL_INLINEASM];  
270     char *lbp = lb;
271
272     if(!pic16_debug_verbose)
273       return;
274
275     va_start(ap,fmt);   
276
277     if (inst && *inst) {
278         if (fmt && *fmt)
279             sprintf(lb,"%s\t",inst);
280         else
281             sprintf(lb,"%s",inst);
282         vsprintf(lb+(strlen(lb)),fmt,ap);
283     }  else
284         vsprintf(lb,fmt,ap);
285
286     while (isspace(*lbp)) lbp++;
287
288     if (lbp && *lbp) 
289         lineCurr = (lineCurr ?
290                     connectLine(lineCurr,newLineNode(lb)) :
291                     (lineHead = newLineNode(lb)));
292     lineCurr->isInline = _G.inLine;
293     lineCurr->isDebug  = _G.debugLine;
294
295     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
296     va_end(ap);
297
298 //      fprintf(stderr, "%s\n", lb);
299 }
300
301
302
303 void pic16_emitpLabel(int key)
304 {
305   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
306 }
307
308 void pic16_emitpLabelFORCE(int key)
309 {
310   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
311 }
312
313 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
314 {
315
316   if(pcop)
317     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
318   else
319     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
320 }
321
322 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
323 {
324   if(pcop)
325     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
326   else
327     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
328 }
329   
330 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
331 {
332
333   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
334
335 }
336
337
338 #if 1
339 #define pic16_emitcode  DEBUGpic16_emitcode
340 #else
341 /*-----------------------------------------------------------------*/
342 /* pic16_emitcode - writes the code into a file : for now it is simple    */
343 /*-----------------------------------------------------------------*/
344 void pic16_emitcode (char *inst,char *fmt, ...)
345 {
346     va_list ap;
347     char lb[INITIAL_INLINEASM];  
348     char *lbp = lb;
349
350     va_start(ap,fmt);   
351
352     if (inst && *inst) {
353         if (fmt && *fmt)
354             sprintf(lb,"%s\t",inst);
355         else
356             sprintf(lb,"%s",inst);
357         vsprintf(lb+(strlen(lb)),fmt,ap);
358     }  else
359         vsprintf(lb,fmt,ap);
360
361     while (isspace(*lbp)) lbp++;
362
363     if (lbp && *lbp) 
364         lineCurr = (lineCurr ?
365                     connectLine(lineCurr,newLineNode(lb)) :
366                     (lineHead = newLineNode(lb)));
367     lineCurr->isInline = _G.inLine;
368     lineCurr->isDebug  = _G.debugLine;
369
370 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
371
372 //    if(pic16_debug_verbose)
373 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
374
375     va_end(ap);
376 }
377 #endif
378
379
380 /*-----------------------------------------------------------------*/
381 /* pic16_emitDebuggerSymbol - associate the current code location  */
382 /*   with a debugger symbol                                        */
383 /*-----------------------------------------------------------------*/
384 void
385 pic16_emitDebuggerSymbol (char * debugSym)
386 {
387   _G.debugLine = 1;
388   pic16_emitcode (";", "%s ==.", debugSym);
389   _G.debugLine = 0;
390 }
391
392
393 /*-----------------------------------------------------------------*/
394 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
395 /*-----------------------------------------------------------------*/
396 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
397 {
398 //    bool r0iu = FALSE , r1iu = FALSE;
399 //    bool r0ou = FALSE , r1ou = FALSE;
400     bool fsr0iu = FALSE, fsr0ou;
401     bool fsr2iu = FALSE, fsr2ou;
402     
403     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
404
405     
406     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
407     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
408     
409     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
410     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
411
412     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
413         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
414         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
415     }
416
417     if(!fsr0iu && !fsr0ou) {
418         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
419         (*aopp)->type = AOP_FSR0;
420
421         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
422         
423       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
424     }
425
426 #if 0
427     /* no usage of FSR2 */
428     if(!fsr2iu && !fsr2ou) {
429         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
430         (*aopp)->type = AOP_FSR2;
431
432       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
433     }
434 #endif
435         
436     /* now we know they both have usage */
437     /* if fsr0 not used in this instruction */
438     if (!fsr0iu) {
439         if (!_G.fsr0Pushed) {
440                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
441                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
442                 _G.fsr0Pushed++;
443         }
444
445         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
446         (*aopp)->type = AOP_FSR0;
447
448 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
449
450       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
451     }
452         
453
454     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
455     assert( 0 );
456
457     return NULL;
458 #if 0
459     /* the logic: if r0 & r1 used in the instruction
460     then we are in trouble otherwise */
461
462     /* first check if r0 & r1 are used by this
463     instruction, in which case we are in trouble */
464     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
465         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
466     {
467         goto endOfWorld;      
468     }
469
470     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
471     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
472
473     /* if no usage of r0 then return it */
474     if (!r0iu && !r0ou) {
475         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
476         (*aopp)->type = AOP_R0; 
477         
478         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
479     }
480
481     /* if no usage of r1 then return it */
482     if (!r1iu && !r1ou) {
483         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
484         (*aopp)->type = AOP_R1;
485
486         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
487     }    
488
489     /* now we know they both have usage */
490     /* if r0 not used in this instruction */
491     if (!r0iu) {
492         /* push it if not already pushed */
493         if (!_G.r0Pushed) {
494           //pic16_emitcode ("push","%s",
495           //          pic16_regWithIdx(R0_IDX)->dname);
496             _G.r0Pushed++ ;
497         }
498         
499         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
500         (*aopp)->type = AOP_R0;
501
502         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
503     }
504
505     /* if r1 not used then */
506
507     if (!r1iu) {
508         /* push it if not already pushed */
509         if (!_G.r1Pushed) {
510           //pic16_emitcode ("push","%s",
511           //          pic16_regWithIdx(R1_IDX)->dname);
512             _G.r1Pushed++ ;
513         }
514         
515         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
516         (*aopp)->type = AOP_R1;
517         return pic16_regWithIdx(R1_IDX);
518     }
519
520 endOfWorld :
521     /* I said end of world but not quite end of world yet */
522     /* if this is a result then we can push it on the stack*/
523     if (result) {
524         (*aopp)->type = AOP_STK;    
525         return NULL;
526     }
527
528     /* other wise this is true end of the world */
529     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
530            "getFreePtr should never reach here");
531     exit(0);
532 #endif
533 }
534
535 /*-----------------------------------------------------------------*/
536 /* newAsmop - creates a new asmOp                                  */
537 /*-----------------------------------------------------------------*/
538 static asmop *newAsmop (short type)
539 {
540     asmop *aop;
541
542     aop = Safe_calloc(1,sizeof(asmop));
543     aop->type = type;
544     return aop;
545 }
546
547 static void genSetDPTR(int n)
548 {
549     if (!n)
550     {
551         pic16_emitcode(";", "Select standard DPTR");
552         pic16_emitcode("mov", "dps, #0x00");
553     }
554     else
555     {
556         pic16_emitcode(";", "Select alternate DPTR");
557         pic16_emitcode("mov", "dps, #0x01");
558     }
559 }
560
561 /*-----------------------------------------------------------------*/
562 /* resolveIfx - converts an iCode ifx into a form more useful for  */
563 /*              generating code                                    */
564 /*-----------------------------------------------------------------*/
565 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
566 {
567   FENTRY2;
568   
569 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
570
571   if(!resIfx) 
572     return;
573
574
575   resIfx->condition = 1;    /* assume that the ifx is true */
576   resIfx->generated = 0;    /* indicate that the ifx has not been used */
577
578   if(!ifx) {
579     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
580
581 #if 1
582     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
583                         __FUNCTION__,__LINE__,resIfx->lbl->key);
584 #endif
585
586   } else {
587     if(IC_TRUE(ifx)) {
588       resIfx->lbl = IC_TRUE(ifx);
589     } else {
590       resIfx->lbl = IC_FALSE(ifx);
591       resIfx->condition = 0;
592     }
593
594 #if 1
595     if(IC_TRUE(ifx)) 
596       DEBUGpic16_emitcode("; +++","ifx true is non-null");
597     else
598       DEBUGpic16_emitcode("; +++","ifx true is null");
599     if(IC_FALSE(ifx)) 
600       DEBUGpic16_emitcode("; +++","ifx false is non-null");
601     else
602       DEBUGpic16_emitcode("; +++","ifx false is null");
603 #endif
604   }
605
606   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
607
608 }
609 #if 0
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type               */
612 /*-----------------------------------------------------------------*/
613 static int pointerCode (sym_link *etype)
614 {
615
616     return PTR_TYPE(SPEC_OCLS(etype));
617
618 }
619 #endif
620
621 /*-----------------------------------------------------------------*/
622 /* aopForSym - for a true symbol                                   */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForSym (iCode *ic, operand *op, bool result)
625 {
626     symbol *sym=OP_SYMBOL(op);
627     asmop *aop;
628     memmap *space= SPEC_OCLS(sym->etype);
629
630     FENTRY2;
631     
632     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
633     
634 //    sym = OP_SYMBOL(op);
635
636     /* if already has one */
637     if (sym->aop) {
638             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
639         return sym->aop;
640     }
641
642 #if 0
643     /* if symbol was initially placed onStack then we must re-place it
644      * to direct memory, since pic16 does not have a specific stack */
645     if(sym->onStack) {
646         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
647     }
648 #endif
649
650
651 #if 0
652     if(sym->iaccess) {
653       if(space->paged) {
654         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
655
656         sym->aop = aop = newAsmop (AOP_PAGED);
657         aop->aopu.aop_dir = sym->rname ;
658         aop->size = getSize(sym->type);
659         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660         pic16_allocDirReg( IC_LEFT(ic) );
661         return aop;
662       }
663       assert( 0 );
664     }
665 #endif
666     
667 #if 1
668     /* assign depending on the storage class */
669     /* if it is on the stack or indirectly addressable */
670     /* space we need to assign either r0 or r1 to it   */    
671     if (sym->onStack)   // || sym->iaccess)
672     {
673       pCodeOp *pcop[4];
674       int i;
675       
676         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
677                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
678         
679         /* acquire a temporary register -- it is saved in function */
680
681         sym->aop = aop = newAsmop(AOP_STA);
682         aop->aopu.stk.stk = sym->stack;
683         aop->size = getSize(sym->type);
684
685
686         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
687         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
688           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
689           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
690           
691           for(i=0;i<aop->size;i++)
692             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
693             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
694         } else
695           for(i=0;i<aop->size;i++) {
696             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
697             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
698           }
699
700
701 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
702
703 #if 1
704         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
705
706         // we do not need to load the value if it is to be defined...
707         if (result) return aop;
708
709         if(_G.accInUse) {
710                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
711         }
712         
713         for(i=0;i<aop->size;i++) {
714
715           /* initialise for stack access via frame pointer */
716           // operands on stack are accessible via "FSR2 + index" with index
717           // starting at 2 for arguments and growing from 0 downwards for
718           // local variables (index == 0 is not assigned so we add one here)
719           {
720             int soffs = sym->stack;
721             if (soffs <= 0) {
722               assert (soffs < 0);
723               soffs++;
724             } // if
725             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
726             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
727                             pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
728           }
729         }
730         
731         if(_G.accInUse) {
732                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
733         }
734         
735         return (aop);
736 #endif
737
738 #if 0
739         /* now assign the address of the variable to 
740         the pointer register */
741         if (aop->type != AOP_STK) {
742
743             if (sym->onStack) {
744                     if ( _G.accInUse )
745                         pic16_emitcode("push","acc");
746
747                     pic16_emitcode("mov","a,_bp");
748                     pic16_emitcode("add","a,#0x%02x",
749                              ((sym->stack < 0) ?
750                               ((char)(sym->stack - _G.nRegsSaved )) :
751                               ((char)sym->stack)) & 0xff);
752                     pic16_emitcode("mov","%s,a",
753                              aop->aopu.aop_ptr->name);
754
755                     if ( _G.accInUse )
756                         pic16_emitcode("pop","acc");
757             } else
758                 pic16_emitcode("mov","%s,#%s",
759                          aop->aopu.aop_ptr->name,
760                          sym->rname);
761             aop->paged = space->paged;
762         } else
763             aop->aopu.aop_stk = sym->stack;
764         return aop;
765 #endif
766
767     }
768 #endif
769
770 #if 0
771     if (sym->onStack && options.stack10bit)
772     {
773         /* It's on the 10 bit stack, which is located in
774          * far data space.
775          */
776          
777       //DEBUGpic16_emitcode(";","%d",__LINE__);
778
779         if ( _G.accInUse )
780                 pic16_emitcode("push","acc");
781
782         pic16_emitcode("mov","a,_bp");
783         pic16_emitcode("add","a,#0x%02x",
784                  ((sym->stack < 0) ?
785                    ((char)(sym->stack - _G.nRegsSaved )) :
786                    ((char)sym->stack)) & 0xff);
787         
788         genSetDPTR(1);
789         pic16_emitcode ("mov","dpx1,#0x40");
790         pic16_emitcode ("mov","dph1,#0x00");
791         pic16_emitcode ("mov","dpl1, a");
792         genSetDPTR(0);
793         
794         if ( _G.accInUse )
795             pic16_emitcode("pop","acc");
796             
797         sym->aop = aop = newAsmop(AOP_DPTR2);
798         aop->size = getSize(sym->type); 
799         return aop;
800     }
801 #endif
802
803 #if 1
804     /* special case for a function */
805     if (IS_FUNC(sym->type)) {   
806         sym->aop = aop = newAsmop(AOP_PCODE);
807         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
808         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
809         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
810         PCOI(aop->aopu.pcop)->index = 0;
811         aop->size = FPTRSIZE; 
812         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
813         return aop;
814     }
815 #endif
816
817
818
819     //DEBUGpic16_emitcode(";","%d",__LINE__);
820     /* if in bit space */
821     if (IN_BITSPACE(space)) {
822         sym->aop = aop = newAsmop (AOP_CRY);
823         aop->aopu.aop_dir = sym->rname ;
824         aop->size = getSize(sym->type);
825         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
826         return aop;
827     }
828     /* if it is in direct space */
829     if (IN_DIRSPACE(space)) {
830         sym->aop = aop = newAsmop (AOP_DIR);
831         aop->aopu.aop_dir = sym->rname ;
832         aop->size = getSize(sym->type);
833         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
834         pic16_allocDirReg( IC_LEFT(ic) );
835         return aop;
836     }
837
838
839     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
840         sym->aop = aop = newAsmop (AOP_DIR);
841         aop->aopu.aop_dir = sym->rname ;
842         aop->size = getSize(sym->type);
843         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
844         pic16_allocDirReg( IC_LEFT(ic) );
845         return aop;
846     }
847
848
849     /* only remaining is far space */
850     sym->aop = aop = newAsmop(AOP_PCODE);
851
852 /* change the next if to 1 to revert to good old immediate code */
853         if(IN_CODESPACE(space)) {
854                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
855                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
856                 PCOI(aop->aopu.pcop)->index = 0;
857         } else {
858                 /* try to allocate via direct register */
859                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
860 //              aop->size = getSize( sym->type );
861         }
862
863         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
864                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
865
866 #if 0
867         if(!pic16_allocDirReg (IC_LEFT(ic)))
868                 return NULL;
869 #endif
870
871         if(IN_DIRSPACE( space ))
872                 aop->size = PTRSIZE;
873         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
874                 aop->size = FPTRSIZE;
875         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
876         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
877         else if(sym->onStack) {
878                 aop->size = PTRSIZE;
879         } else {
880           if(SPEC_SCLS(sym->etype) == S_PDATA) {
881             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
882             aop->size = FPTRSIZE;
883           } else
884                 assert( 0 );
885         }
886
887     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
888
889     /* if it is in code space */
890     if (IN_CODESPACE(space))
891         aop->code = 1;
892
893     return aop;     
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* aopForRemat - rematerialzes an object                           */
898 /*-----------------------------------------------------------------*/
899 static asmop *aopForRemat (operand *op) // x symbol *sym)
900 {
901   symbol *sym = OP_SYMBOL(op);
902   operand *refop;
903   iCode *ic = NULL, *oldic;
904   asmop *aop = newAsmop(AOP_PCODE);
905   int val = 0;
906   int offset = 0;
907   int viaimmd=0;
908
909     FENTRY2;
910     
911         ic = sym->rematiCode;
912
913         if(IS_OP_POINTER(op)) {
914                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
915         }
916
917         for (;;) {
918                 oldic = ic;
919
920 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
921         
922                 if (ic->op == '+') {
923                         val += (int) operandLitValue(IC_RIGHT(ic));
924                 } else if (ic->op == '-') {
925                         val -= (int) operandLitValue(IC_RIGHT(ic));
926                 } else
927                         break;
928                 
929                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
930         }
931
932         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
933         refop = IC_LEFT(ic);
934
935         if(!op->isaddr)viaimmd++; else viaimmd=0;
936                 
937 /* set the following if to 1 to revert to good old immediate code */
938         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
939                 || viaimmd) {
940
941                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
942
943                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
944
945 #if 0
946                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
947 #else
948                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
949 #endif
950
951                 PCOI(aop->aopu.pcop)->index = val;
952                 
953                 aop->size = getSize( sym->type );
954         } else {
955                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
956
957                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
958                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
959
960                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
961         }
962
963
964         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
965                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
966 #if 0
967                 val, IS_PTR_CONST(operandType(op)));
968 #else
969                 val, IS_CODEPTR(operandType(op)));
970 #endif
971
972 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
973
974         pic16_allocDirReg (IC_LEFT(ic));
975
976         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
977                 aop->code = 1;
978
979   return aop;        
980 }
981
982 #if 0
983 static int aopIdx (asmop *aop, int offset)
984 {
985   if(!aop)
986     return -1;
987
988   if(aop->type !=  AOP_REG)
989     return -2;
990         
991   return aop->aopu.aop_reg[offset]->rIdx;
992
993 }
994 #endif
995
996 /*-----------------------------------------------------------------*/
997 /* regsInCommon - two operands have some registers in common       */
998 /*-----------------------------------------------------------------*/
999 static bool regsInCommon (operand *op1, operand *op2)
1000 {
1001     symbol *sym1, *sym2;
1002     int i;
1003
1004     /* if they have registers in common */
1005     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1006         return FALSE ;
1007
1008     sym1 = OP_SYMBOL(op1);
1009     sym2 = OP_SYMBOL(op2);
1010
1011     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1012         return FALSE ;
1013
1014     for (i = 0 ; i < sym1->nRegs ; i++) {
1015         int j;
1016         if (!sym1->regs[i])
1017             continue ;
1018
1019         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1020             if (!sym2->regs[j])
1021                 continue ;
1022
1023             if (sym2->regs[j] == sym1->regs[i])
1024                 return TRUE ;
1025         }
1026     }
1027
1028     return FALSE ;
1029 }
1030
1031 /*-----------------------------------------------------------------*/
1032 /* operandsEqu - equivalent                                        */
1033 /*-----------------------------------------------------------------*/
1034 static bool operandsEqu ( operand *op1, operand *op2)
1035 {
1036     symbol *sym1, *sym2;
1037
1038     /* if they not symbols */
1039     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1040         return FALSE;
1041
1042     sym1 = OP_SYMBOL(op1);
1043     sym2 = OP_SYMBOL(op2);
1044
1045     /* if both are itemps & one is spilt
1046        and the other is not then false */
1047     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1048         sym1->isspilt != sym2->isspilt )
1049         return FALSE ;
1050
1051     /* if they are the same */
1052     if (sym1 == sym2)
1053         return TRUE ;
1054
1055     if (sym1->rname[0] && sym2->rname[0]
1056         && strcmp (sym1->rname, sym2->rname) == 0)
1057         return TRUE;
1058
1059
1060     /* if left is a tmp & right is not */
1061     if (IS_ITEMP(op1)  && 
1062         !IS_ITEMP(op2) &&
1063         sym1->isspilt  &&
1064         (sym1->usl.spillLoc == sym2))
1065         return TRUE;
1066
1067     if (IS_ITEMP(op2)  && 
1068         !IS_ITEMP(op1) &&
1069         sym2->isspilt  &&
1070         sym1->level > 0 &&
1071         (sym2->usl.spillLoc == sym1))
1072         return TRUE ;
1073
1074     return FALSE ;
1075 }
1076
1077 /*-----------------------------------------------------------------*/
1078 /* pic16_sameRegs - two asmops have the same registers                   */
1079 /*-----------------------------------------------------------------*/
1080 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1081 {
1082     int i;
1083
1084     if (aop1 == aop2)
1085         return TRUE ;
1086
1087     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1088                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1089
1090     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1091
1092     if (aop1->type != AOP_REG ||
1093         aop2->type != AOP_REG )
1094         return FALSE ;
1095
1096     /* This is a bit too restrictive if one is a subset of the other...
1097     if (aop1->size != aop2->size )
1098         return FALSE ;
1099     */
1100
1101     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1102 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1103
1104 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1105         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1106             return FALSE ;
1107     }
1108
1109     return TRUE ;
1110 }
1111
1112 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1113 {
1114     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1115                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1116
1117     if(aop1 == aop2)return TRUE;
1118     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1119       
1120       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1121     
1122   return TRUE;
1123 }
1124
1125
1126 /*-----------------------------------------------------------------*/
1127 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1128 /*-----------------------------------------------------------------*/
1129 void pic16_aopOp (operand *op, iCode *ic, bool result)
1130 {
1131     asmop *aop;
1132     symbol *sym;
1133     int i;
1134
1135     if (!op)
1136         return ;
1137
1138     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1139
1140     /* if this a literal */
1141     if (IS_OP_LITERAL(op)) {
1142         op->aop = aop = newAsmop(AOP_LIT);
1143         aop->aopu.aop_lit = op->operand.valOperand;
1144         aop->size = getSize(operandType(op));
1145         return;
1146     }
1147
1148     {
1149       sym_link *type = operandType(op);
1150 #if 0
1151       if(IS_PTR_CONST(type))
1152 #else
1153       if(IS_CODEPTR(type))
1154 #endif
1155         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1156     }
1157
1158     /* if already has a asmop then continue */
1159     if (op->aop)
1160         return ;
1161
1162     /* if the underlying symbol has a aop */
1163     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1164       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1165         op->aop = OP_SYMBOL(op)->aop;
1166         return;
1167     }
1168
1169     /* if this is a true symbol */
1170     if (IS_TRUE_SYMOP(op)) {    
1171         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1172       op->aop = aopForSym(ic, op, result);
1173       return ;
1174     }
1175
1176     /* this is a temporary : this has
1177     only four choices :
1178     a) register
1179     b) spillocation
1180     c) rematerialize 
1181     d) conditional   
1182     e) can be a return use only */
1183
1184     sym = OP_SYMBOL(op);
1185
1186     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1187     /* if the type is a conditional */
1188     if (sym->regType == REG_CND) {
1189         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1190         aop->size = 0;
1191         return;
1192     }
1193
1194     /* if it is spilt then two situations
1195     a) is rematerialize 
1196     b) has a spill location */
1197     if (sym->isspilt || sym->nRegs == 0) {
1198
1199 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1200       DEBUGpic16_emitcode(";","%d",__LINE__);
1201         /* rematerialize it NOW */
1202         if (sym->remat) {
1203
1204             sym->aop = op->aop = aop = aopForRemat (op);
1205 //            aop->size = getSize(sym->type);
1206 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1207             return;
1208         }
1209
1210 #if 1
1211         if (sym->accuse) {
1212             int i;
1213             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1214             aop->size = getSize(sym->type);
1215             for ( i = 0 ; i < 1 ; i++ ) {
1216                 aop->aopu.aop_str[i] = accUse[i];
1217 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1218             }
1219             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1220             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1221             return;  
1222         }
1223 #endif
1224
1225 #if 1
1226         if (sym->ruonly) {
1227           /*
1228           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1229           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1230           //pic16_allocDirReg (IC_LEFT(ic));
1231           aop->size = getSize(sym->type);
1232           */
1233
1234           unsigned i;
1235
1236           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1237           aop->size = getSize(sym->type);
1238           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1239             aop->aopu.aop_str[i] = fReturn[i];
1240
1241           DEBUGpic16_emitcode(";","%d",__LINE__);
1242           return;
1243         }
1244 #endif
1245         /* else spill location  */
1246         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1247             /* force a new aop if sizes differ */
1248             sym->usl.spillLoc->aop = NULL;
1249         }
1250
1251 #if 0
1252         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1253                             __FUNCTION__,__LINE__,
1254                             sym->usl.spillLoc->rname,
1255                             sym->rname, sym->usl.spillLoc->offset);
1256 #endif
1257
1258         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1259         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1260         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1261           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1262                                                   getSize(sym->type), 
1263                                                   sym->usl.spillLoc->offset, op);
1264         } else {
1265           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1266           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1267           assert (getSize(sym->type) <= 1);
1268           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1269         }
1270         aop->size = getSize(sym->type);
1271
1272         return;
1273     }
1274
1275     {
1276       sym_link *type = operandType(op);
1277 #if 0
1278       if(IS_PTR_CONST(type)) 
1279 #else
1280       if(IS_CODEPTR(type)) 
1281 #endif
1282         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1283     }
1284
1285     /* must be in a register */
1286     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1287     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1288     aop->size = sym->nRegs;
1289     for ( i = 0 ; i < sym->nRegs ;i++)
1290         aop->aopu.aop_reg[i] = sym->regs[i];
1291 }
1292
1293 /*-----------------------------------------------------------------*/
1294 /* pic16_freeAsmop - free up the asmop given to an operand               */
1295 /*----------------------------------------------------------------*/
1296 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1297 {   
1298     asmop *aop ;
1299
1300     if (!op)
1301         aop = aaop;
1302     else 
1303         aop = op->aop;
1304
1305     if (!aop)
1306         return ;
1307
1308     if (aop->freed)
1309         goto dealloc; 
1310
1311     aop->freed = 1;
1312
1313     /* depending on the asmop type only three cases need work AOP_RO
1314        , AOP_R1 && AOP_STK */
1315 #if 1
1316     switch (aop->type) {
1317         case AOP_FSR0 :
1318             if (_G.fsr0Pushed ) {
1319                 if (pop) {
1320                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1321                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1322 //                    pic16_emitcode ("pop","ar0");
1323                     _G.fsr0Pushed--;
1324                 }
1325             }
1326             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1327             break;
1328
1329         case AOP_FSR2 :
1330             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1331             break;
1332
1333         case AOP_R0 :
1334             if (_G.r0Pushed ) {
1335                 if (pop) {
1336                     pic16_emitcode ("pop","ar0");     
1337                     _G.r0Pushed--;
1338                 }
1339             }
1340             bitVectUnSetBit(ic->rUsed,R0_IDX);
1341             break;
1342
1343         case AOP_R1 :
1344             if (_G.r1Pushed ) {
1345                 if (pop) {
1346                     pic16_emitcode ("pop","ar1");
1347                     _G.r1Pushed--;
1348                 }
1349             }
1350             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1351             break;
1352
1353         case AOP_STA:
1354           {
1355             int i;
1356
1357               /* we must store the result on stack */
1358               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1359                 // operands on stack are accessible via "FSR2 + index" with index
1360                 // starting at 2 for arguments and growing from 0 downwards for
1361                 // local variables (index == 0 is not assigned so we add one here)
1362                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1363                 if (soffs <= 0) {
1364                   assert (soffs < 0);
1365                   soffs++;
1366                 } // if
1367                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1368                 for(i=0;i<aop->size;i++) {
1369                   /* initialise for stack access via frame pointer */
1370                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1371                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1372                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1373                 }
1374         
1375                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1376               }
1377
1378               if(!_G.resDirect) {
1379                 for(i=0;i<aop->size;i++)
1380                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1381               }
1382               _G.resDirect = 0;
1383           }
1384           break;
1385 #if 0
1386         case AOP_STK :
1387         {
1388             int sz = aop->size;    
1389             int stk = aop->aopu.aop_stk + aop->size;
1390             bitVectUnSetBit(ic->rUsed,R0_IDX);
1391             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1392
1393             getFreePtr(ic,&aop,FALSE);
1394             
1395             if (options.stack10bit)
1396             {
1397                 /* I'm not sure what to do here yet... */
1398                 /* #STUB */
1399                 fprintf(stderr, 
1400                         "*** Warning: probably generating bad code for "
1401                         "10 bit stack mode.\n");
1402             }
1403             
1404             if (stk) {
1405                 pic16_emitcode ("mov","a,_bp");
1406                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1407                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1408             } else {
1409                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1410             }
1411
1412             while (sz--) {
1413                 pic16_emitcode("pop","acc");
1414                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1415                 if (!sz) break;
1416                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1417             }
1418             op->aop = aop;
1419             pic16_freeAsmop(op,NULL,ic,TRUE);
1420             if (_G.r0Pushed) {
1421                 pic16_emitcode("pop","ar0");
1422                 _G.r0Pushed--;
1423             }
1424
1425             if (_G.r1Pushed) {
1426                 pic16_emitcode("pop","ar1");
1427                 _G.r1Pushed--;
1428             }       
1429         }
1430 #endif
1431
1432     }
1433 #endif
1434
1435 dealloc:
1436     /* all other cases just dealloc */
1437     if (op ) {
1438         op->aop = NULL;
1439         if (IS_SYMOP(op)) {
1440             OP_SYMBOL(op)->aop = NULL;    
1441             /* if the symbol has a spill */
1442             if (SPIL_LOC(op))
1443                 SPIL_LOC(op)->aop = NULL;
1444         }
1445     }
1446 }
1447
1448 /*-----------------------------------------------------------------*/
1449 /* pic16_aopGet - for fetching value of the aop                          */
1450 /*-----------------------------------------------------------------*/
1451 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1452 {
1453     char *s = buffer ;
1454     char *rs;
1455
1456     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1457
1458     /* offset is greater than size then zero */
1459     if (offset > (aop->size - 1) &&
1460         aop->type != AOP_LIT)
1461         return zero;
1462
1463     /* depending on type */
1464     switch (aop->type) {
1465
1466     case AOP_FSR0:
1467     case AOP_FSR2:
1468       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1469       rs = Safe_calloc(1, strlen(s)+1);
1470       strcpy(rs, s);
1471       return (rs);
1472       
1473 #if 0
1474       /* if we need to increment it */
1475       while (offset > aop->coff)
1476         {
1477           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478           aop->coff++;
1479         }
1480
1481       while (offset < aop->coff)
1482         {
1483           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1484           aop->coff--;
1485         }
1486       aop->coff = offset;
1487       if (aop->paged)
1488         {
1489           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1490           return (dname ? "acc" : "a");
1491         }
1492       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1493       rs = Safe_calloc (1, strlen (s) + 1);
1494       strcpy (rs, s);
1495       return rs;
1496 #endif
1497
1498         
1499     case AOP_IMMD:
1500         if (bit16) 
1501             sprintf (s,"%s",aop->aopu.aop_immd);
1502         else
1503             if (offset) 
1504                 sprintf(s,"(%s >> %d)",
1505                         aop->aopu.aop_immd,
1506                         offset*8);
1507             else
1508                 sprintf(s,"%s",
1509                         aop->aopu.aop_immd);
1510         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1511         rs = Safe_calloc(1,strlen(s)+1);
1512         strcpy(rs,s);   
1513         return rs;
1514         
1515     case AOP_DIR:
1516       if (offset) {
1517         sprintf(s,"(%s + %d)",
1518                 aop->aopu.aop_dir,
1519                 offset);
1520         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1521       } else
1522             sprintf(s,"%s",aop->aopu.aop_dir);
1523         rs = Safe_calloc(1,strlen(s)+1);
1524         strcpy(rs,s);   
1525         return rs;
1526         
1527     case AOP_REG:
1528       //if (dname) 
1529       //    return aop->aopu.aop_reg[offset]->dname;
1530       //else
1531             return aop->aopu.aop_reg[offset]->name;
1532         
1533     case AOP_CRY:
1534       //pic16_emitcode(";","%d",__LINE__);
1535       return aop->aopu.aop_dir;
1536         
1537     case AOP_ACC:
1538         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1539 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1540 //        assert( 0 );
1541 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1542         rs = Safe_strdup("WREG");
1543         return (rs);
1544
1545     case AOP_LIT:
1546         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1547         rs = Safe_calloc(1,strlen(s)+1);
1548         strcpy(rs,s);   
1549         return rs;
1550         
1551     case AOP_STR:
1552         aop->coff = offset ;
1553         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1554             dname)
1555             return "acc";
1556         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1557         
1558         return aop->aopu.aop_str[offset];
1559         
1560     case AOP_PCODE:
1561       {
1562         pCodeOp *pcop = aop->aopu.pcop;
1563         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1564         if(pcop->name) {
1565           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1566           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1567           if (offset) {
1568             sprintf(s,"(%s + %d)", pcop->name, offset);
1569           } else {
1570             sprintf(s,"%s", pcop->name);
1571           }
1572         } else
1573           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1574
1575       }
1576       rs = Safe_calloc(1,strlen(s)+1);
1577       strcpy(rs,s);   
1578       return rs;
1579
1580 #if 0
1581     case AOP_PAGED:
1582       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1583       if (offset) {
1584         sprintf(s,"(%s + %d)",
1585                 aop->aopu.aop_dir,
1586                 offset);
1587       } else
1588             sprintf(s,"%s",aop->aopu.aop_dir);
1589       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1590       rs = Safe_calloc(1,strlen(s)+1);
1591       strcpy(rs,s);   
1592       return rs;
1593 #endif
1594
1595     case AOP_STA:
1596         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1597         return (rs);
1598         
1599     case AOP_STK:
1600 //        pCodeOp *pcop = aop->aop
1601         break;
1602
1603     }
1604
1605     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1606     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1607            "aopget got unsupported aop->type");
1608     exit(0);
1609 }
1610
1611
1612
1613 /* lock has the following meaning: When allocating temporary registers
1614  * for stack variables storage, the value of the temporary register is
1615  * saved on stack. Its value is restored at the end. This procedure is
1616  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1617  * a possibility that before a call to pic16_aopOp, a temporary register
1618  * is allocated for a while and it is freed after some time, this will
1619  * mess the stack and values will not be restored properly. So use lock=1
1620  * to allocate temporary registers used internally by the programmer, and
1621  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1622  * to inform the compiler developer about a possible bug. This is an internal
1623  * feature for developing the compiler -- VR */
1624  
1625 int _TempReg_lock = 0;
1626 /*-----------------------------------------------------------------*/
1627 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1628 /*-----------------------------------------------------------------*/
1629 pCodeOp *pic16_popGetTempReg(int lock)
1630 {
1631   pCodeOp *pcop;
1632   symbol *cfunc;
1633
1634 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1635     if(_TempReg_lock) {
1636 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1637     }
1638     
1639     _TempReg_lock += lock;
1640     
1641     cfunc = currFunc;
1642     currFunc = NULL;
1643
1644     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1645     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1646       PCOR(pcop)->r->wasUsed=1;
1647       PCOR(pcop)->r->isFree=0;
1648
1649       /* push value on stack */
1650       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1651     }
1652
1653     currFunc = cfunc;
1654
1655   return pcop;
1656 }
1657
1658 /*-----------------------------------------------------------------*/
1659 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1660 /*                            don't save if inside v               */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1663 {
1664   pCodeOp *pcop;
1665   symbol *cfunc;
1666
1667 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1668
1669     if(_TempReg_lock) {
1670 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1671     }
1672
1673     _TempReg_lock += lock;
1674
1675     cfunc = currFunc;
1676     currFunc = NULL;
1677
1678     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1679     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1680       PCOR(pcop)->r->wasUsed=1;
1681       PCOR(pcop)->r->isFree=0;
1682
1683       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1684       /* push value on stack */
1685         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1686       }
1687     }
1688
1689     currFunc = cfunc;
1690
1691   return pcop;
1692 }
1693
1694
1695 /*-----------------------------------------------------------------*/
1696 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1697 /*-----------------------------------------------------------------*/
1698 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1699 {
1700   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1701
1702   _TempReg_lock -= lock;
1703
1704   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1705     PCOR(pcop)->r->isFree = 1;
1706     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1707   }
1708 }
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1711 /*-----------------------------------------------------------------*/
1712 pCodeOp *pic16_popGetLabel(unsigned int key)
1713 {
1714
1715   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1716
1717   if(key>max_key)
1718     max_key = key;
1719
1720   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1721 }
1722
1723 /*-----------------------------------------------------------------*/
1724 /* pic16_popCopyReg - copy a pcode operator                              */
1725 /*-----------------------------------------------------------------*/
1726 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1727 {
1728   pCodeOpReg *pcor;
1729
1730   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1731   pcor->pcop.type = pc->pcop.type;
1732   if(pc->pcop.name) {
1733     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1734       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1735   } else
1736     pcor->pcop.name = NULL;
1737
1738   pcor->r = pc->r;
1739   pcor->rIdx = pc->rIdx;
1740   pcor->r->wasUsed=1;
1741   pcor->instance = pc->instance;
1742
1743 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1744
1745   return PCOP(pcor);
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1750 /*-----------------------------------------------------------------*/
1751 pCodeOp *pic16_popGetLit(int lit)
1752 {
1753   return pic16_newpCodeOpLit(lit);
1754 }
1755
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1758 /*-----------------------------------------------------------------*/
1759 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1760 {
1761   return pic16_newpCodeOpLit2(lit, arg2);
1762 }
1763
1764
1765 /*-----------------------------------------------------------------*/
1766 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1769 {
1770   return pic16_newpCodeOpImmd(name, offset,index, 0);
1771 }
1772
1773
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGet - asm operator to pcode operator conversion              */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetWithString(char *str)
1778 {
1779   pCodeOp *pcop;
1780
1781
1782   if(!str) {
1783     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1784     exit (1);
1785   }
1786
1787   pcop = pic16_newpCodeOp(str,PO_STR);
1788
1789   return pcop;
1790 }
1791
1792 /*-----------------------------------------------------------------*/
1793 /* pic16_popRegFromString -                                        */
1794 /*-----------------------------------------------------------------*/
1795 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1796 {
1797
1798   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1799   pcop->type = PO_DIR;
1800
1801   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1802   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1803
1804   if(!str)
1805     str = "BAD_STRING";
1806
1807   pcop->name = Safe_calloc(1,strlen(str)+1);
1808   strcpy(pcop->name,str);
1809
1810   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1811
1812   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1813
1814   /* make sure that register doesn't exist,
1815    * and operand isn't NULL
1816    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1817   if((PCOR(pcop)->r == NULL) 
1818     && (op)
1819     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1820 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1821 //              __FUNCTION__, __LINE__, str, size, offset);
1822
1823     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1824     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1825
1826   }
1827   PCOR(pcop)->instance = offset;
1828
1829   return pcop;
1830 }
1831
1832 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1833 {
1834   pCodeOp *pcop;
1835
1836 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1837
1838         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1839         PCOR(pcop)->rIdx = rIdx;
1840         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1841
1842         PCOR(pcop)->r->isFree = 0;
1843         PCOR(pcop)->r->wasUsed = 1;
1844
1845         pcop->type = PCOR(pcop)->r->pc_type;
1846
1847   return pcop;
1848 }
1849
1850 /*---------------------------------------------------------------------------------*/
1851 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1852 /*                 VR 030601                                                       */
1853 /*---------------------------------------------------------------------------------*/
1854 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1855 {
1856   pCodeOpReg2 *pcop2;
1857   pCodeOp *temp;
1858   
1859         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1860
1861         /* comment the following check, so errors to throw up */
1862 //      if(!pcop2)return NULL;
1863
1864         temp = pic16_popGet(aop_dst, offset);
1865         pcop2->pcop2 = temp;
1866         
1867   return PCOP(pcop2);
1868 }
1869
1870
1871
1872 /*--------------------------------------------------------------------------------.-*/
1873 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1874 /*                  VR 030601 , adapted by Hans Dorn                                */
1875 /*--------------------------------------------------------------------------------.-*/
1876 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1877 {
1878   pCodeOpReg2 *pcop2;
1879  
1880         pcop2 = (pCodeOpReg2 *)src;
1881         pcop2->pcop2 = dst;
1882         
1883         return PCOP(pcop2);
1884 }
1885
1886
1887
1888 /*---------------------------------------------------------------------------------*/
1889 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1890 /*                     movff instruction                                           */
1891 /*---------------------------------------------------------------------------------*/
1892 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1893 {
1894   pCodeOpReg2 *pcop2;
1895
1896         if(!noalloc) {
1897                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1898                 pcop2->pcop2 = pic16_popCopyReg(dst);
1899         } else {
1900                 /* the pCodeOp may be already allocated */
1901                 pcop2 = (pCodeOpReg2 *)(src);
1902                 pcop2->pcop2 = (pCodeOp *)(dst);
1903         }
1904
1905   return PCOP(pcop2);
1906 }
1907
1908
1909 /*-----------------------------------------------------------------*/
1910 /* pic16_popGet - asm operator to pcode operator conversion              */
1911 /*-----------------------------------------------------------------*/
1912 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1913 {
1914   //char *s = buffer ;
1915   char *rs;
1916   pCodeOp *pcop;
1917
1918     FENTRY2;
1919     /* offset is greater than
1920     size then zero */
1921
1922 //    if (offset > (aop->size - 1) &&
1923 //        aop->type != AOP_LIT)
1924 //      return NULL;  //zero;
1925
1926     /* depending on type */
1927     switch (aop->type) {
1928         
1929     case AOP_R0:
1930     case AOP_R1:
1931     case AOP_DPTR:
1932     case AOP_DPTR2:
1933         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1934         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1935         assert( 0 );
1936         return NULL;
1937
1938
1939     case AOP_FSR0:
1940     case AOP_FSR2:
1941       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1942       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1943       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1944       PCOR(pcop)->r->wasUsed = 1;
1945       PCOR(pcop)->r->isFree = 0;
1946       
1947       PCOR(pcop)->instance = offset;
1948       pcop->type = PCOR(pcop)->r->pc_type;
1949       return (pcop);
1950
1951     case AOP_IMMD:
1952       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1953       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1954
1955     case AOP_STA:
1956       /* pCodeOp is already allocated from aopForSym */
1957         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1958         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1959           
1960       return (pcop);
1961       
1962     case AOP_ACC:
1963       {
1964         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1965
1966         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1967
1968         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1969         
1970         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1971         PCOR(pcop)->rIdx = rIdx;
1972         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1973         PCOR(pcop)->r->wasUsed=1;
1974         PCOR(pcop)->r->isFree=0;
1975
1976         PCOR(pcop)->instance = offset;
1977         pcop->type = PCOR(pcop)->r->pc_type;
1978 //      rs = aop->aopu.aop_reg[offset]->name;
1979 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1980         return pcop;
1981
1982
1983 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1984 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1985
1986 //      assert( 0 );
1987       }
1988         
1989     case AOP_DIR:
1990       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1991       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1992         
1993 #if 0
1994     case AOP_PAGED:
1995       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1996       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1997 #endif
1998
1999     case AOP_REG:
2000       {
2001         int rIdx;
2002         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2003         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2004
2005         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2006         
2007         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2008 //      pcop->type = PO_GPR_REGISTER;
2009         PCOR(pcop)->rIdx = rIdx;
2010         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2011         PCOR(pcop)->r->wasUsed=1;
2012         PCOR(pcop)->r->isFree=0;
2013
2014         PCOR(pcop)->instance = offset;
2015         pcop->type = PCOR(pcop)->r->pc_type;
2016         
2017         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2018         rs = aop->aopu.aop_reg[offset]->name;
2019         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2020         return pcop;
2021       }
2022
2023     case AOP_CRY:
2024         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2025
2026       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2027       PCOR(pcop)->instance = offset;
2028       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2029       //if(PCOR(pcop)->r == NULL)
2030       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2031       return pcop;
2032         
2033     case AOP_LIT:
2034         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2035       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2036
2037     case AOP_STR:
2038       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2039       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2040
2041       /*
2042       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2043       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2044       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2045       pcop->type = PCOR(pcop)->r->pc_type;
2046       pcop->name = PCOR(pcop)->r->name;
2047
2048       return pcop;
2049       */
2050
2051     case AOP_PCODE:
2052       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2053                           __LINE__, 
2054                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2055       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2056       switch( aop->aopu.pcop->type ) {
2057         case PO_DIR: PCOR(pcop)->instance += offset; break;
2058         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2059         case PO_WREG:
2060             assert (offset==0);
2061             break;
2062         default:
2063           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2064           assert( 0 );  /* should never reach here */;
2065       }
2066       return pcop;
2067     }
2068
2069     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2070            "pic16_popGet got unsupported aop->type");
2071     exit(0);
2072 }
2073 /*-----------------------------------------------------------------*/
2074 /* pic16_aopPut - puts a string for a aop                                */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_aopPut (asmop *aop, char *s, int offset)
2077 {
2078     char *d = buffer ;
2079     symbol *lbl ;
2080
2081     return;
2082
2083     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2084
2085     if (aop->size && offset > ( aop->size - 1)) {
2086         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2087                "pic16_aopPut got offset > aop->size");
2088         exit(0);
2089     }
2090
2091     /* will assign value to value */
2092     /* depending on where it is ofcourse */
2093     switch (aop->type) {
2094     case AOP_DIR:
2095       if (offset) {
2096         sprintf(d,"(%s + %d)",
2097                 aop->aopu.aop_dir,offset);
2098         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2099
2100       } else
2101             sprintf(d,"%s",aop->aopu.aop_dir);
2102         
2103         if (strcmp(d,s)) {
2104           DEBUGpic16_emitcode(";","%d",__LINE__);
2105           if(strcmp(s,"W"))
2106             pic16_emitcode("movf","%s,w",s);
2107           pic16_emitcode("movwf","%s",d);
2108
2109           if(strcmp(s,"W")) {
2110             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2111             if(offset >= aop->size) {
2112               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2113               break;
2114             } else
2115               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2116           }
2117
2118           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2119
2120
2121         }
2122         break;
2123         
2124     case AOP_REG:
2125       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2126         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2127           /*
2128             if (*s == '@'           ||
2129                 strcmp(s,"r0") == 0 ||
2130                 strcmp(s,"r1") == 0 ||
2131                 strcmp(s,"r2") == 0 ||
2132                 strcmp(s,"r3") == 0 ||
2133                 strcmp(s,"r4") == 0 ||
2134                 strcmp(s,"r5") == 0 ||
2135                 strcmp(s,"r6") == 0 || 
2136                 strcmp(s,"r7") == 0 )
2137                 pic16_emitcode("mov","%s,%s  ; %d",
2138                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2139             else
2140           */
2141
2142           if(strcmp(s,"W")==0 )
2143             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2144
2145           pic16_emitcode("movwf","%s",
2146                    aop->aopu.aop_reg[offset]->name);
2147
2148           if(strcmp(s,zero)==0) {
2149             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2150
2151           } else if(strcmp(s,"W")==0) {
2152             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2153             pcop->type = PO_GPR_REGISTER;
2154
2155             PCOR(pcop)->rIdx = -1;
2156             PCOR(pcop)->r = NULL;
2157
2158             DEBUGpic16_emitcode(";","%d",__LINE__);
2159             pcop->name = Safe_strdup(s);
2160             pic16_emitpcode(POC_MOVFW,pcop);
2161             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2162           } else if(strcmp(s,one)==0) {
2163             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2164             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2165           } else {
2166             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2167           }
2168         }
2169         break;
2170         
2171     case AOP_DPTR:
2172     case AOP_DPTR2:
2173     
2174     if (aop->type == AOP_DPTR2)
2175     {
2176         genSetDPTR(1);
2177     }
2178     
2179         if (aop->code) {
2180             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2181                    "pic16_aopPut writting to code space");
2182             exit(0);
2183         }
2184         
2185         while (offset > aop->coff) {
2186             aop->coff++;
2187             pic16_emitcode ("inc","dptr");
2188         }
2189         
2190         while (offset < aop->coff) {
2191             aop->coff-- ;
2192             pic16_emitcode("lcall","__decdptr");
2193         }
2194         
2195         aop->coff = offset;
2196         
2197         /* if not in accumulater */
2198         MOVA(s);        
2199         
2200         pic16_emitcode ("movx","@dptr,a");
2201         
2202     if (aop->type == AOP_DPTR2)
2203     {
2204         genSetDPTR(0);
2205     }
2206         break;
2207         
2208     case AOP_R0:
2209     case AOP_R1:
2210         while (offset > aop->coff) {
2211             aop->coff++;
2212             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2213         }
2214         while (offset < aop->coff) {
2215             aop->coff-- ;
2216             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2217         }
2218         aop->coff = offset;
2219         
2220         if (aop->paged) {
2221             MOVA(s);           
2222             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2223             
2224         } else
2225             if (*s == '@') {
2226                 MOVA(s);
2227                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2228             } else
2229                 if (strcmp(s,"r0") == 0 ||
2230                     strcmp(s,"r1") == 0 ||
2231                     strcmp(s,"r2") == 0 ||
2232                     strcmp(s,"r3") == 0 ||
2233                     strcmp(s,"r4") == 0 ||
2234                     strcmp(s,"r5") == 0 ||
2235                     strcmp(s,"r6") == 0 || 
2236                     strcmp(s,"r7") == 0 ) {
2237                     char buffer[10];
2238                     sprintf(buffer,"a%s",s);
2239                     pic16_emitcode("mov","@%s,%s",
2240                              aop->aopu.aop_ptr->name,buffer);
2241                 } else
2242                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2243         
2244         break;
2245         
2246     case AOP_STK:
2247         if (strcmp(s,"a") == 0)
2248             pic16_emitcode("push","acc");
2249         else
2250             pic16_emitcode("push","%s",s);
2251         
2252         break;
2253         
2254     case AOP_CRY:
2255         /* if bit variable */
2256         if (!aop->aopu.aop_dir) {
2257             pic16_emitcode("clr","a");
2258             pic16_emitcode("rlc","a");
2259         } else {
2260             if (s == zero) 
2261                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2262             else
2263                 if (s == one)
2264                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2265                 else
2266                     if (!strcmp(s,"c"))
2267                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2268                     else {
2269                         lbl = newiTempLabel(NULL);
2270                         
2271                         if (strcmp(s,"a")) {
2272                             MOVA(s);
2273                         }
2274                         pic16_emitcode("clr","c");
2275                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2276                         pic16_emitcode("cpl","c");
2277                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2278                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2279                     }
2280         }
2281         break;
2282         
2283     case AOP_STR:
2284         aop->coff = offset;
2285         if (strcmp(aop->aopu.aop_str[offset],s))
2286             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2287         break;
2288         
2289     case AOP_ACC:
2290         aop->coff = offset;
2291         if (!offset && (strcmp(s,"acc") == 0))
2292             break;
2293         
2294         if (strcmp(aop->aopu.aop_str[offset],s))
2295             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2296         break;
2297
2298     default :
2299         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2300 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2301 //             "pic16_aopPut got unsupported aop->type");
2302 //      exit(0);    
2303     }    
2304
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2309 /*-----------------------------------------------------------------*/
2310 void pic16_mov2w (asmop *aop, int offset)
2311 {
2312   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2313
2314   if(is_LitAOp(aop))
2315     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2316   else
2317     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2318 }
2319
2320 static void mov2f(asmop *dst, asmop *src, int offset)
2321 {
2322   if(is_LitAOp(src)) {
2323     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2324     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2325   } else {
2326     if(pic16_sameRegsOfs(src, dst, offset))return;
2327     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2328                       pic16_popGet(dst, offset)));
2329   }
2330 }
2331
2332 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2333 {
2334   if(is_LitAOp(src)) {
2335     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2336     pic16_emitpcode(POC_MOVWF, dst);
2337   } else {
2338     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2339   }
2340 }
2341
2342 void pic16_testStackOverflow(void)
2343 {
2344 #define GSTACK_TEST_NAME        "__gstack_test"
2345
2346   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2347   
2348   {
2349     symbol *sym;
2350
2351       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2352       strcpy(sym->rname, GSTACK_TEST_NAME);
2353       checkAddSym(&externs, sym);
2354   }
2355
2356 }
2357
2358 /* push pcop into stack */
2359 void pic16_pushpCodeOp(pCodeOp *pcop)
2360 {
2361 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2362   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2363   if(pic16_options.gstack)
2364     pic16_testStackOverflow();
2365     
2366 }
2367
2368 /* pop pcop from stack */
2369 void pic16_poppCodeOp(pCodeOp *pcop)
2370 {
2371   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2372   if(pic16_options.gstack)
2373     pic16_testStackOverflow();
2374 }
2375
2376
2377 /*-----------------------------------------------------------------*/
2378 /* pushw - pushes wreg to stack                                    */
2379 /*-----------------------------------------------------------------*/
2380 void pushw(void)
2381 {
2382   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2383   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2384   if(pic16_options.gstack)
2385     pic16_testStackOverflow();
2386 }
2387
2388                 
2389 /*-----------------------------------------------------------------*/
2390 /* pushaop - pushes aop to stack                                   */
2391 /*-----------------------------------------------------------------*/
2392 void pushaop(asmop *aop, int offset)
2393 {
2394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2395
2396   if(is_LitAOp(aop)) {
2397     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2398     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2399   } else {
2400     pic16_emitpcode(POC_MOVFF,
2401       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2402   }
2403
2404   if(pic16_options.gstack)
2405     pic16_testStackOverflow();
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* popaop - pops aop from stack                                    */
2410 /*-----------------------------------------------------------------*/
2411 void popaop(asmop *aop, int offset)
2412 {
2413   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2414   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2415   if(pic16_options.gstack)
2416     pic16_testStackOverflow();
2417 }
2418
2419 void popaopidx(asmop *aop, int offset, int index)
2420 {
2421   int ofs=1;
2422
2423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2424
2425     if(STACK_MODEL_LARGE)ofs++;
2426
2427     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2428     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2429     if(pic16_options.gstack)
2430       pic16_testStackOverflow();
2431 }
2432
2433 #if !(USE_GENERIC_SIGNED_SHIFT)
2434 /*-----------------------------------------------------------------*/
2435 /* reAdjustPreg - points a register back to where it should        */
2436 /*-----------------------------------------------------------------*/
2437 static void reAdjustPreg (asmop *aop)
2438 {
2439     int size ;
2440
2441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2442     aop->coff = 0;
2443     if ((size = aop->size) <= 1)
2444         return ;
2445     size-- ;
2446     switch (aop->type) {
2447         case AOP_R0 :
2448         case AOP_R1 :
2449             while (size--)
2450                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2451             break;          
2452         case AOP_DPTR :
2453         case AOP_DPTR2:
2454             if (aop->type == AOP_DPTR2)
2455             {
2456                 genSetDPTR(1);
2457             } 
2458             while (size--)
2459             {
2460                 pic16_emitcode("lcall","__decdptr");
2461             }
2462                 
2463             if (aop->type == AOP_DPTR2)
2464             {
2465                 genSetDPTR(0);
2466             }                
2467             break;  
2468
2469     }   
2470
2471 }
2472 #endif
2473
2474 #if 0
2475 /*-----------------------------------------------------------------*/
2476 /* opIsGptr: returns non-zero if the passed operand is             */   
2477 /* a generic pointer type.                                         */
2478 /*-----------------------------------------------------------------*/ 
2479 static int opIsGptr(operand *op)
2480 {
2481     sym_link *type = operandType(op);
2482     
2483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2484     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2485     {
2486         return 1;
2487     }
2488     return 0;        
2489 }
2490 #endif
2491
2492 /*-----------------------------------------------------------------*/
2493 /* pic16_getDataSize - get the operand data size                         */
2494 /*-----------------------------------------------------------------*/
2495 int pic16_getDataSize(operand *op)
2496 {
2497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2498
2499
2500     return AOP_SIZE(op);
2501
2502     // tsd- in the pic port, the genptr size is 1, so this code here
2503     // fails. ( in the 8051 port, the size was 4).
2504 #if 0
2505     int size;
2506     size = AOP_SIZE(op);
2507     if (size == GPTRSIZE)
2508     {
2509         sym_link *type = operandType(op);
2510         if (IS_GENPTR(type))
2511         {
2512             /* generic pointer; arithmetic operations
2513              * should ignore the high byte (pointer type).
2514              */
2515             size--;
2516     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2517         }
2518     }
2519     return size;
2520 #endif
2521 }
2522
2523 /*-----------------------------------------------------------------*/
2524 /* pic16_outAcc - output Acc                                             */
2525 /*-----------------------------------------------------------------*/
2526 void pic16_outAcc(operand *result)
2527 {
2528   int size,offset;
2529   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2530   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2531
2532
2533   size = pic16_getDataSize(result);
2534   if(size){
2535     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2536     size--;
2537     offset = 1;
2538     /* unsigned or positive */
2539     while(size--)
2540       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2541   }
2542
2543 }
2544
2545 /*-----------------------------------------------------------------*/
2546 /* pic16_outBitC - output a bit C                                  */
2547 /*                 Move to result the value of Carry flag -- VR    */
2548 /*-----------------------------------------------------------------*/
2549 void pic16_outBitC(operand *result)
2550 {
2551   int i;
2552
2553     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2554
2555     /* if the result is bit */
2556     if (AOP_TYPE(result) == AOP_CRY) {
2557         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2558         pic16_aopPut(AOP(result),"c",0);
2559     } else {
2560
2561         i = AOP_SIZE(result);
2562         while(i--) {
2563                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2564         }
2565         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2566     }
2567 }
2568
2569 /*-----------------------------------------------------------------*/
2570 /* pic16_outBitOp - output a bit from Op                           */
2571 /*                 Move to result the value of set/clr op -- VR    */
2572 /*-----------------------------------------------------------------*/
2573 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2574 {
2575   int i;
2576
2577     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2578
2579     /* if the result is bit */
2580     if (AOP_TYPE(result) == AOP_CRY) {
2581         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2582         pic16_aopPut(AOP(result),"c",0);
2583     } else {
2584
2585         i = AOP_SIZE(result);
2586         while(i--) {
2587                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2588         }
2589         pic16_emitpcode(POC_RRCF, pcop);          
2590         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2591     }
2592 }
2593
2594 /*-----------------------------------------------------------------*/
2595 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2596 /*-----------------------------------------------------------------*/
2597 void pic16_toBoolean(operand *oper)
2598 {
2599     int size = AOP_SIZE(oper) - 1;
2600     int offset = 1;
2601
2602     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2603
2604     if ( AOP_TYPE(oper) != AOP_ACC) {
2605       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2606     }
2607     while (size--) {
2608       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2609     }
2610 }
2611
2612
2613 #if !defined(GEN_Not)
2614 /*-----------------------------------------------------------------*/
2615 /* genNot - generate code for ! operation                          */
2616 /*-----------------------------------------------------------------*/
2617 static void pic16_genNot (iCode *ic)
2618 {
2619   symbol *tlbl;
2620   int size;
2621
2622   FENTRY;
2623   /* assign asmOps to operand & result */
2624   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2625   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2626
2627   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2628   /* if in bit space then a special case */
2629   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2630     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2631       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2632       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2633     } else {
2634       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2635       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2636       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2637     }
2638     goto release;
2639   }
2640
2641   size = AOP_SIZE(IC_LEFT(ic));
2642   if(size == 1) {
2643     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2644     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2645     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2646     goto release;
2647   }
2648   pic16_toBoolean(IC_LEFT(ic));
2649
2650   tlbl = newiTempLabel(NULL);
2651   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2652   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2653   pic16_outBitC(IC_RESULT(ic));
2654
2655  release:    
2656   /* release the aops */
2657   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2658   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2659 }
2660 #endif
2661
2662
2663 #if !defined(GEN_Cpl)
2664 /*-----------------------------------------------------------------*/
2665 /* genCpl - generate code for complement                           */
2666 /*-----------------------------------------------------------------*/
2667 static void pic16_genCpl (iCode *ic)
2668 {
2669   int offset = 0;
2670   int size ;
2671
2672     FENTRY;
2673     /* assign asmOps to operand & result */
2674     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2675     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2676
2677     /* if both are in bit space then 
2678     a special case */
2679     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2680         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2681
2682         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2683         pic16_emitcode("cpl","c"); 
2684         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2685         goto release; 
2686     } 
2687
2688     size = AOP_SIZE(IC_RESULT(ic));
2689     while (size--) {
2690 /*
2691         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2692         MOVA(l);       
2693         pic16_emitcode("cpl","a");
2694         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2695 */
2696         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2697               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2698         } else {
2699                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2700                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2701         }
2702         offset++;
2703
2704     }
2705
2706
2707 release:
2708     /* release the aops */
2709     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2710     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2711 }
2712 #endif
2713
2714 /*-----------------------------------------------------------------*/
2715 /* genUminusFloat - unary minus for floating points                */
2716 /*-----------------------------------------------------------------*/
2717 static void genUminusFloat(operand *op,operand *result)
2718 {
2719   int size ,offset =0 ;
2720   
2721     FENTRY;
2722     /* for this we just need to flip the 
2723     first it then copy the rest in place */
2724     size = AOP_SIZE(op);
2725
2726     while(size--) {
2727       mov2f(AOP(result), AOP(op), offset);
2728       offset++;
2729     }
2730     
2731     /* toggle the MSB's highest bit */
2732     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2733 }
2734
2735 /*-----------------------------------------------------------------*/
2736 /* genUminus - unary minus code generation                         */
2737 /*-----------------------------------------------------------------*/
2738 static void genUminus (iCode *ic)
2739 {
2740   int size, i;
2741   sym_link *optype, *rtype;
2742   symbol *label;
2743   int needLabel=0;
2744
2745     FENTRY;     
2746     
2747     /* assign asmops */
2748     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2749     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2750
2751     /* if both in bit space then special case */
2752     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2753       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2754         
2755         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2756         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2757         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2758         goto release; 
2759     } 
2760
2761     optype = operandType(IC_LEFT(ic));
2762     rtype = operandType(IC_RESULT(ic));
2763
2764     /* if float then do float stuff */
2765     if (IS_FLOAT(optype)) {
2766       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2767       goto release;
2768     }
2769
2770     /* otherwise subtract from zero by taking the 2's complement */
2771     size = AOP_SIZE(IC_LEFT(ic));
2772     label = newiTempLabel ( NULL );
2773     
2774     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2775       for (i=size-1; i > 0; i--) {
2776         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2777       } // for
2778       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2779       for (i=1; i < size; i++) {
2780         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2781         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2782       } // for
2783     } else {
2784       for (i=size-1; i >= 0; i--) {
2785         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2786         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2787       } // for
2788       if (size > 1) {
2789         for (i=0; i < size-2; i++) {
2790           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2791           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2792         } // for
2793         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2794       } // if
2795       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2796     }
2797     if (needLabel)
2798       pic16_emitpLabel (label->key);
2799
2800 release:
2801     /* release the aops */
2802     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2803     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2804 }
2805
2806 #if 0
2807 /*-----------------------------------------------------------------*/
2808 /* saveRegisters - will look for a call and save the registers     */
2809 /*-----------------------------------------------------------------*/
2810 static void saveRegisters(iCode *lic) 
2811 {
2812     int i;
2813     iCode *ic;
2814     bitVect *rsave;
2815     sym_link *dtype;
2816
2817     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2818     /* look for call */
2819     for (ic = lic ; ic ; ic = ic->next) 
2820         if (ic->op == CALL || ic->op == PCALL)
2821             break;
2822
2823     if (!ic) {
2824         fprintf(stderr,"found parameter push with no function call\n");
2825         return ;
2826     }
2827
2828     /* if the registers have been saved already then
2829     do nothing */
2830     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2831         return ;
2832
2833     /* find the registers in use at this time 
2834     and push them away to safety */
2835     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2836                           ic->rUsed);
2837
2838     ic->regsSaved = 1;
2839     if (options.useXstack) {
2840         if (bitVectBitValue(rsave,R0_IDX))
2841             pic16_emitcode("mov","b,r0");
2842         pic16_emitcode("mov","r0,%s",spname);
2843         for (i = 0 ; i < pic16_nRegs ; i++) {
2844             if (bitVectBitValue(rsave,i)) {
2845                 if (i == R0_IDX)
2846                     pic16_emitcode("mov","a,b");
2847                 else
2848                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2849                 pic16_emitcode("movx","@r0,a");
2850                 pic16_emitcode("inc","r0");
2851             }
2852         }
2853         pic16_emitcode("mov","%s,r0",spname);
2854         if (bitVectBitValue(rsave,R0_IDX))
2855             pic16_emitcode("mov","r0,b");           
2856     }// else
2857     //for (i = 0 ; i < pic16_nRegs ; i++) {
2858     //    if (bitVectBitValue(rsave,i))
2859     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2860     //}
2861
2862     dtype = operandType(IC_LEFT(ic));
2863     if (currFunc && dtype && 
2864         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2865         IFFUNC_ISISR(currFunc->type) &&
2866         !ic->bankSaved) 
2867
2868         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2869
2870 }
2871 /*-----------------------------------------------------------------*/
2872 /* unsaveRegisters - pop the pushed registers                      */
2873 /*-----------------------------------------------------------------*/
2874 static void unsaveRegisters (iCode *ic)
2875 {
2876     int i;
2877     bitVect *rsave;
2878
2879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2880     /* find the registers in use at this time 
2881     and push them away to safety */
2882     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2883                           ic->rUsed);
2884     
2885     if (options.useXstack) {
2886         pic16_emitcode("mov","r0,%s",spname);   
2887         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2888             if (bitVectBitValue(rsave,i)) {
2889                 pic16_emitcode("dec","r0");
2890                 pic16_emitcode("movx","a,@r0");
2891                 if (i == R0_IDX)
2892                     pic16_emitcode("mov","b,a");
2893                 else
2894                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2895             }       
2896
2897         }
2898         pic16_emitcode("mov","%s,r0",spname);
2899         if (bitVectBitValue(rsave,R0_IDX))
2900             pic16_emitcode("mov","r0,b");
2901     } //else
2902     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2903     //    if (bitVectBitValue(rsave,i))
2904     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2905     //}
2906
2907 }  
2908 #endif
2909
2910 #if 0  // patch 14
2911 /*-----------------------------------------------------------------*/
2912 /* pushSide -                                                      */
2913 /*-----------------------------------------------------------------*/
2914 static void pushSide(operand * oper, int size)
2915 {
2916         int offset = 0;
2917     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2918         while (size--) {
2919                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2920                 if (AOP_TYPE(oper) != AOP_REG &&
2921                     AOP_TYPE(oper) != AOP_DIR &&
2922                     strcmp(l,"a") ) {
2923                         pic16_emitcode("mov","a,%s",l);
2924                         pic16_emitcode("push","acc");
2925                 } else
2926                         pic16_emitcode("push","%s",l);
2927         }
2928 }
2929 #endif // patch 14
2930
2931 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2932 {
2933   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2934     pic16_emitpcode(POC_MOVFW, src);
2935     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2936   } else {
2937     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2938         src, pic16_popGet(AOP(op), offset)));
2939   }
2940 }
2941
2942
2943 /*-----------------------------------------------------------------*/
2944 /* assignResultValue - assign results to oper, rescall==1 is       */
2945 /*                     called from genCall() or genPcall()         */
2946 /*-----------------------------------------------------------------*/
2947 static void assignResultValue(operand * oper, int rescall)
2948 {
2949   int size = AOP_SIZE(oper);
2950   int offset=0;
2951   
2952     FENTRY2;
2953 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2954     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2955
2956     if(rescall) {
2957       /* assign result from a call/pcall function() */
2958                 
2959       /* function results are stored in a special order,
2960        * see top of file with Function return policy, or manual */
2961
2962       if(size <= 4) {
2963         /* 8-bits, result in WREG */
2964         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2965                         
2966         if(size>1) {
2967           /* 16-bits, result in PRODL:WREG */
2968           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2969         }
2970                         
2971         if(size>2) {
2972           /* 24-bits, result in PRODH:PRODL:WREG */
2973           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2974         }
2975                         
2976         if(size>3) {
2977           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2978           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2979         }
2980       
2981       } else {
2982         /* >32-bits, result on stack, and FSR0 points to beginning.
2983          * Fix stack when done */
2984         /* FIXME FIXME */
2985 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2986         while (size--) {
2987 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2988 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2989                 
2990           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2991           GpsuedoStkPtr++;
2992         }
2993                         
2994         /* fix stack */
2995         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2996         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2997         if(STACK_MODEL_LARGE) {
2998           emitSKPNC;
2999           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3000         }
3001       }                 
3002     } else {
3003       int areg = 0;             /* matching argument register */
3004       
3005 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3006       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3007
3008
3009       /* its called from genReceive (probably) -- VR */
3010       /* I hope this code will not be called from somewhere else in the future! 
3011        * We manually set the pseudo stack pointer in genReceive. - dw
3012        */
3013       if(!GpsuedoStkPtr && _G.useWreg) {
3014 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3015
3016         /* The last byte in the assignment is in W */
3017         if(areg <= GpsuedoStkPtr) {
3018           size--;
3019           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3020           offset++;
3021 //          debugf("receive from WREG\n", 0);
3022         }
3023         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3024       }
3025 //      GpsuedoStkPtr++;
3026       _G.stack_lat = AOP_SIZE(oper)-1;
3027
3028       while (size) {
3029         size--;
3030         GpsuedoStkPtr++;
3031         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3032 //        debugf("receive from STACK\n", 0);
3033         offset++;
3034       }
3035     }
3036 }
3037
3038
3039 /*-----------------------------------------------------------------*/
3040 /* genIpush - generate code for pushing this gets a little complex */
3041 /*-----------------------------------------------------------------*/
3042 static void genIpush (iCode *ic)
3043 {
3044 //  int size, offset=0;
3045
3046   FENTRY;
3047   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3048
3049   if(ic->parmPush) {
3050     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3051
3052     /* send to stack as normal */
3053     addSet(&_G.sendSet,ic);
3054 //    addSetHead(&_G.sendSet,ic);
3055     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3056   }
3057
3058         
3059 #if 0
3060     int size, offset = 0 ;
3061     char *l;
3062
3063
3064     /* if this is not a parm push : ie. it is spill push 
3065     and spill push is always done on the local stack */
3066     if (!ic->parmPush) {
3067
3068         /* and the item is spilt then do nothing */
3069         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3070             return ;
3071
3072         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3073         size = AOP_SIZE(IC_LEFT(ic));
3074         /* push it on the stack */
3075         while(size--) {
3076             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3077             if (*l == '#') {
3078                 MOVA(l);
3079                 l = "acc";
3080             }
3081             pic16_emitcode("push","%s",l);
3082         }
3083         return ;        
3084     }
3085
3086     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3087 #endif
3088 }
3089
3090 /*-----------------------------------------------------------------*/
3091 /* genIpop - recover the registers: can happen only for spilling   */
3092 /*-----------------------------------------------------------------*/
3093 static void genIpop (iCode *ic)
3094 {
3095   FENTRY;
3096   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3097 #if 0
3098     int size,offset ;
3099
3100
3101     /* if the temp was not pushed then */
3102     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3103         return ;
3104
3105     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3106     size = AOP_SIZE(IC_LEFT(ic));
3107     offset = (size-1);
3108     while (size--) 
3109         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3110                                    FALSE,TRUE));
3111
3112     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3113 #endif
3114 }
3115
3116 #if 0
3117 /*-----------------------------------------------------------------*/
3118 /* unsaverbank - restores the resgister bank from stack            */
3119 /*-----------------------------------------------------------------*/
3120 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3121 {
3122   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3123 #if 0
3124     int i;
3125     asmop *aop ;
3126     regs *r = NULL;
3127
3128     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3129     if (popPsw) {
3130         if (options.useXstack) {
3131             aop = newAsmop(0);
3132             r = getFreePtr(ic,&aop,FALSE);
3133             
3134             
3135             pic16_emitcode("mov","%s,_spx",r->name);
3136             pic16_emitcode("movx","a,@%s",r->name);
3137             pic16_emitcode("mov","psw,a");
3138             pic16_emitcode("dec","%s",r->name);
3139             
3140         }else
3141             pic16_emitcode ("pop","psw");
3142     }
3143
3144     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3145         if (options.useXstack) {       
3146             pic16_emitcode("movx","a,@%s",r->name);
3147             //pic16_emitcode("mov","(%s+%d),a",
3148             //       regspic16[i].base,8*bank+regspic16[i].offset);
3149             pic16_emitcode("dec","%s",r->name);
3150
3151         } else 
3152           pic16_emitcode("pop",""); //"(%s+%d)",
3153         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3154     }
3155
3156     if (options.useXstack) {
3157
3158         pic16_emitcode("mov","_spx,%s",r->name);
3159         pic16_freeAsmop(NULL,aop,ic,TRUE);
3160
3161     }
3162 #endif 
3163 }
3164
3165 /*-----------------------------------------------------------------*/
3166 /* saverbank - saves an entire register bank on the stack          */
3167 /*-----------------------------------------------------------------*/
3168 static void saverbank (int bank, iCode *ic, bool pushPsw)
3169 {
3170   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3171 #if 0
3172     int i;
3173     asmop *aop ;
3174     regs *r = NULL;
3175
3176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3177     if (options.useXstack) {
3178
3179         aop = newAsmop(0);
3180         r = getFreePtr(ic,&aop,FALSE);  
3181         pic16_emitcode("mov","%s,_spx",r->name);
3182
3183     }
3184
3185     for (i = 0 ; i < pic16_nRegs ;i++) {
3186         if (options.useXstack) {
3187             pic16_emitcode("inc","%s",r->name);
3188             //pic16_emitcode("mov","a,(%s+%d)",
3189             //         regspic16[i].base,8*bank+regspic16[i].offset);
3190             pic16_emitcode("movx","@%s,a",r->name);           
3191         } else 
3192           pic16_emitcode("push","");// "(%s+%d)",
3193                      //regspic16[i].base,8*bank+regspic16[i].offset);
3194     }
3195     
3196     if (pushPsw) {
3197         if (options.useXstack) {
3198             pic16_emitcode("mov","a,psw");
3199             pic16_emitcode("movx","@%s,a",r->name);     
3200             pic16_emitcode("inc","%s",r->name);
3201             pic16_emitcode("mov","_spx,%s",r->name);       
3202             pic16_freeAsmop (NULL,aop,ic,TRUE);
3203             
3204         } else
3205             pic16_emitcode("push","psw");
3206         
3207         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3208     }
3209     ic->bankSaved = 1;
3210 #endif
3211 }
3212 #endif  /* 0 */
3213
3214
3215 static int wparamCmp(void *p1, void *p2)
3216 {
3217   return (!strcmp((char *)p1, (char *)p2));
3218 }
3219
3220 int inWparamList(char *s)
3221 {
3222   return isinSetWith(wparamList, s, wparamCmp);
3223
3224
3225
3226 /*-----------------------------------------------------------------*/
3227 /* genCall - generates a call statement                            */
3228 /*-----------------------------------------------------------------*/
3229 static void genCall (iCode *ic)
3230 {
3231   sym_link *ftype;   
3232   int stackParms=0;
3233   int use_wreg=0;
3234   int inwparam=0;
3235   char *fname;
3236   
3237     FENTRY;
3238
3239     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3240     /* if caller saves & we have not saved then */
3241 //    if (!ic->regsSaved)
3242 //      saveRegisters(ic);
3243
3244         /* initialise stackParms for IPUSH pushes */
3245 //      stackParms = psuedoStkPtr;
3246 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3247     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3248     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3249
3250 #if 0
3251     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3252 #endif
3253
3254     /* if send set is not empty the assign */
3255     if (_G.sendSet) {
3256       iCode *sic;
3257       int psuedoStkPtr=-1; 
3258       int firstTimeThruLoop = 1;
3259
3260
3261         /* reverse sendSet if function is not reentrant */
3262         if(!IFFUNC_ISREENT(ftype))
3263           _G.sendSet = reverseSet(_G.sendSet);
3264
3265         /* First figure how many parameters are getting passed */
3266         stackParms = 0;
3267         use_wreg = 0;
3268         
3269         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3270           int size;
3271 //          int offset = 0;
3272
3273             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3274             size = AOP_SIZE(IC_LEFT(sic));
3275
3276             stackParms += size;
3277
3278             /* pass the last byte through WREG */
3279             if(inwparam) {
3280
3281               while (size--) {
3282                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3283                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3284                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3285
3286                 if(!firstTimeThruLoop) {
3287                   /* If this is not the first time we've been through the loop
3288                    * then we need to save the parameter in a temporary
3289                    * register. The last byte of the last parameter is
3290                    * passed in W. */
3291
3292                   pushw();
3293 //                  --psuedoStkPtr;             // sanity check
3294                   use_wreg = 1;
3295                 }
3296                 
3297                 firstTimeThruLoop=0;
3298
3299                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3300
3301 //                offset++;
3302               }
3303             } else {
3304               /* all arguments are passed via stack */
3305               use_wreg = 0;
3306
3307               while (size--) {
3308                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3309                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3310                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3311
3312 //                pushaop(AOP(IC_LEFT(sic)), size);
3313                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3314                 pushw();
3315               }
3316             }
3317
3318             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3319           }
3320
3321           if(inwparam) {
3322             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3323               pushw();  /* save last parameter to stack if functions has varargs */
3324               use_wreg = 0;
3325             } else
3326               use_wreg = 1;
3327           } else use_wreg = 0;
3328
3329           _G.stackRegSet = _G.sendSet;
3330           _G.sendSet = NULL;
3331     }
3332
3333     /* make the call */
3334     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3335
3336     GpsuedoStkPtr=0;
3337     
3338     /* if we need to assign a result value */
3339     if ((IS_ITEMP(IC_RESULT(ic))
3340           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3341               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3342         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3343
3344       _G.accInUse++;
3345       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3346       _G.accInUse--;
3347
3348       assignResultValue(IC_RESULT(ic), 1);
3349
3350       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3351                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3352                 
3353       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3354     }
3355
3356     if(!stackParms && ic->parmBytes) {
3357       stackParms = ic->parmBytes;
3358     }
3359       
3360     stackParms -= use_wreg;
3361     
3362     if(stackParms>0) {
3363       if(stackParms == 1) {
3364         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3365       } else {
3366         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3367         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3368       }
3369       if(STACK_MODEL_LARGE) {
3370         emitSKPNC;
3371         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3372       }
3373     }
3374
3375 #if 0
3376     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3377 #endif
3378
3379     /* adjust the stack for parameters if required */
3380 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3381
3382 #if 0
3383       /* if register bank was saved then pop them */
3384       if (ic->bankSaved)
3385         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3386
3387       /* if we hade saved some registers then unsave them */
3388       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3389         unsaveRegisters (ic);
3390 #endif
3391 }
3392
3393
3394
3395 /*-----------------------------------------------------------------*/
3396 /* genPcall - generates a call by pointer statement                */
3397 /*            new version, created from genCall - HJD              */
3398 /*-----------------------------------------------------------------*/
3399 static void genPcall (iCode *ic)
3400 {
3401   sym_link *ftype, *fntype;
3402   int stackParms=0;
3403   symbol *retlbl = newiTempLabel(NULL);
3404   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3405   
3406     FENTRY;
3407
3408     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3409     fntype = operandType( IC_LEFT(ic) )->next;
3410
3411     /* if send set is not empty the assign */
3412     if (_G.sendSet) {
3413       iCode *sic;
3414       int psuedoStkPtr=-1; 
3415
3416       /* reverse sendSet if function is not reentrant */
3417       if(!IFFUNC_ISREENT(fntype))
3418         _G.sendSet = reverseSet(_G.sendSet);
3419
3420       stackParms = 0;
3421       
3422       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3423         int size;
3424
3425           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3426           size = AOP_SIZE(IC_LEFT(sic));
3427           stackParms += size;
3428
3429           /* all parameters are passed via stack, since WREG is clobbered
3430            * by the calling sequence */
3431           while (size--) {
3432             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3433             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3434             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3435
3436             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3437             pushw();
3438           }
3439
3440           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3441       }
3442
3443       _G.stackRegSet = _G.sendSet;
3444       _G.sendSet = NULL;
3445     }
3446
3447     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3448
3449     // push return address
3450     // push $ on return stack, then replace with retlbl
3451
3452     /* Thanks to Thorsten Klose for pointing out that the following
3453      * snippet should be interrupt safe */
3454     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3455     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3456
3457     pic16_emitpcodeNULLop(POC_PUSH);
3458
3459     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3460     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3461     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3462     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3463     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3465
3466
3467     /* restore interrupt control register */
3468     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3469     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3470
3471     /* make the call by writing the pointer into pc */
3472     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3473     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3474
3475     // note: MOVFF to PCL not allowed
3476     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3477     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3478
3479
3480     /* return address is here: (X) */
3481     pic16_emitpLabelFORCE(retlbl->key);
3482
3483     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3484
3485     GpsuedoStkPtr=0;
3486     /* if we need assign a result value */
3487     if ((IS_ITEMP(IC_RESULT(ic))
3488           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3489               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3490         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3491
3492       _G.accInUse++;
3493       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3494       _G.accInUse--;
3495
3496       assignResultValue(IC_RESULT(ic), 1);
3497
3498       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3500                 
3501       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3502     }
3503
3504 //    stackParms -= use_wreg;
3505     
3506     if(stackParms>0) {
3507       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3508       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3509       if(STACK_MODEL_LARGE) {
3510         emitSKPNC;
3511         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3512       }
3513     }
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* resultRemat - result  is rematerializable                       */
3518 /*-----------------------------------------------------------------*/
3519 static int resultRemat (iCode *ic)
3520 {
3521   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3522   if (SKIP_IC(ic) || ic->op == IFX)
3523     return 0;
3524
3525   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3526     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3527     if (sym->remat && !POINTER_SET(ic)) 
3528       return 1;
3529   }
3530
3531   return 0;
3532 }
3533
3534 #if defined(__BORLANDC__) || defined(_MSC_VER)
3535 #define STRCASECMP stricmp
3536 #else
3537 #define STRCASECMP strcasecmp
3538 #endif
3539
3540 #if 0
3541 /*-----------------------------------------------------------------*/
3542 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3543 /*-----------------------------------------------------------------*/
3544 static bool inExcludeList(char *s)
3545 {
3546   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3547     int i =0;
3548     
3549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3550     if (options.excludeRegs[i] &&
3551     STRCASECMP(options.excludeRegs[i],"none") == 0)
3552         return FALSE ;
3553
3554     for ( i = 0 ; options.excludeRegs[i]; i++) {
3555         if (options.excludeRegs[i] &&
3556         STRCASECMP(s,options.excludeRegs[i]) == 0)
3557             return TRUE;
3558     }
3559     return FALSE ;
3560 }
3561 #endif
3562
3563 /*-----------------------------------------------------------------*/
3564 /* genFunction - generated code for function entry                 */
3565 /*-----------------------------------------------------------------*/
3566 static void genFunction (iCode *ic)
3567 {
3568   symbol *sym;
3569   sym_link *ftype;
3570   
3571     FENTRY;
3572     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3573
3574     pic16_labelOffset += (max_key+4);
3575     max_key=0;
3576     GpsuedoStkPtr=0;
3577     _G.nRegsSaved = 0;
3578         
3579     ftype = operandType(IC_LEFT(ic));
3580     sym = OP_SYMBOL(IC_LEFT(ic));
3581
3582     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3583       /* create an absolute section at the interrupt vector:
3584        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3585       symbol *asym;
3586       char asymname[128];
3587       pBlock *apb;
3588
3589 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3590
3591 #if 0
3592         {
3593           int i, found=-1;
3594
3595             sym = OP_SYMBOL( IC_LEFT(ic));
3596             for(i=0;i<=2;i++) {
3597               if(interrupts[i]->name
3598                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3599                   found = i;
3600                   break;
3601               }
3602             }
3603                         
3604             if(found == -1) {
3605               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3606                             __FILE__, __LINE__, sym->name);
3607 //              assert( 0 );
3608             }
3609             _G.interruptvector = found;
3610         }
3611 #endif
3612
3613         if(FUNC_INTNO(sym->type) == 256)
3614           sprintf(asymname, "ivec_%s", sym->name);
3615         else
3616           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3617         asym = newSymbol(asymname, 0);
3618
3619         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3620         pic16_addpBlock( apb );
3621
3622         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3623         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3624         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3625                 
3626         /* mark the end of this tiny function */
3627         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3628
3629         {
3630           absSym *abSym;
3631
3632             abSym = Safe_calloc(1, sizeof(absSym));
3633             strcpy(abSym->name, asymname);
3634
3635             switch( FUNC_INTNO(sym->type) ) {
3636               case 0: abSym->address = 0x000000; break;
3637               case 1: abSym->address = 0x000008; break;
3638               case 2: abSym->address = 0x000018; break;
3639               
3640               default:
3641                 abSym->address = -1; break;
3642             }
3643
3644             /* relocate interrupt vectors if needed */
3645             if(abSym->address != -1)
3646               abSym->address += pic16_options.ivt_loc;
3647
3648             addSet(&absSymSet, abSym);
3649         }
3650     }
3651
3652     /* create the function header */
3653     pic16_emitcode(";","-----------------------------------------");
3654     pic16_emitcode(";"," function %s",sym->name);
3655     pic16_emitcode(";","-----------------------------------------");
3656
3657     pic16_emitcode("","%s:",sym->rname);
3658     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3659
3660
3661     {
3662       absSym *ab;
3663
3664         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3665           if(!strcmp(ab->name, sym->rname)) {
3666             pic16_pBlockConvert2Absolute(pb);
3667             break;
3668           }
3669         }
3670     }
3671
3672
3673     if(IFFUNC_ISNAKED(ftype)) {
3674       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3675       return;
3676     }
3677         
3678     /* if critical function then turn interrupts off */
3679     if (IFFUNC_ISCRITICAL(ftype)) {
3680       //pic16_emitcode("clr","ea");
3681     }
3682
3683     _G.fregsUsed = sym->regsUsed;
3684
3685     /* if this is an interrupt service routine then
3686      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3687     if (IFFUNC_ISISR(sym->type)) {
3688         _G.usefastretfie = 1;   /* use shadow registers by default */
3689         
3690         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3691         if(!FUNC_ISSHADOWREGS(sym->type)) {
3692           /* do not save WREG,STATUS,BSR for high priority interrupts
3693            * because they are stored in the hardware shadow registers already */
3694           _G.usefastretfie = 0;
3695           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3696           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3697           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3698         }
3699
3700         /* these should really be optimized somehow, because not all
3701          * interrupt handlers modify them */
3702         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3703         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3704         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3705         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3706         
3707 //        pic16_pBlockConvert2ISR(pb);
3708                 
3709     }
3710
3711     /* emit code to setup stack frame if user enabled,
3712      * and function is not main() */
3713     
3714     //fprintf(stderr, "function name: %s\n", sym->name);
3715     if(strcmp(sym->name, "main")) {
3716       if(0 || !options.ommitFramePtr || sym->regsUsed) {
3717         /* setup the stack frame */
3718         if(STACK_MODEL_LARGE)
3719           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3720         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3721
3722         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3723         if(STACK_MODEL_LARGE)
3724           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3725       }
3726     }
3727
3728     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3729           && sym->stack) {
3730
3731       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3732
3733       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3734       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3735       emitSKPC;
3736       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3737     }
3738           
3739     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3740       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3741         _G.useWreg = 0;
3742       else
3743         _G.useWreg = 1;
3744     } else
3745       _G.useWreg = 0;
3746
3747     /* if callee-save to be used for this function
3748      * then save the registers being used in this function */
3749 //    if (IFFUNC_CALLEESAVES(sym->type))
3750     {
3751       int i;
3752
3753         /* if any registers used */
3754         if (sym->regsUsed) {
3755           /* save the registers used */
3756           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3757           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3758           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3759             if (bitVectBitValue(sym->regsUsed,i)) {
3760               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3761               _G.nRegsSaved++;
3762
3763               if(!pic16_regWithIdx(i)->wasUsed) {
3764                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3765                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3766                 pic16_regWithIdx(i)->wasUsed = 1;
3767               }
3768             }
3769           }
3770           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3771         }
3772     }
3773         
3774     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3775 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3776 }
3777
3778 /*-----------------------------------------------------------------*/
3779 /* genEndFunction - generates epilogue for functions               */
3780 /*-----------------------------------------------------------------*/
3781 static void genEndFunction (iCode *ic)
3782 {
3783   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3784
3785     FENTRY;
3786
3787     if(IFFUNC_ISNAKED(sym->type)) {
3788       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3789       return;
3790     }
3791
3792     _G.stack_lat = 0;
3793
3794     /* add code for ISCRITICAL */
3795     if(IFFUNC_ISCRITICAL(sym->type)) {
3796       /* if critical function, turn on interrupts */
3797       
3798       /* TODO: add code here -- VR */
3799     }
3800     
3801 //    sym->regsUsed = _G.fregsUsed;
3802     
3803     /* now we need to restore the registers */
3804     /* if any registers used */
3805     if (sym->regsUsed) {
3806       int i;
3807
3808         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3809         /* restore registers used */
3810         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3811         for ( i = sym->regsUsed->size; i >= 0; i--) {
3812           if (bitVectBitValue(sym->regsUsed,i)) {
3813             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3814             _G.nRegsSaved--;
3815           }
3816         }
3817         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3818
3819     }
3820
3821     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3822           && sym->stack) {
3823       if (sym->stack == 1) {
3824         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3825         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3826       } else {
3827         // we have to add more than one...
3828         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3829         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3830         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3831         emitSKPNC;
3832         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3833         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3834         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3835       }
3836     }
3837
3838     if(strcmp(sym->name, "main")) {
3839       if(0 || !options.ommitFramePtr || sym->regsUsed) {
3840         /* restore stack frame */
3841         if(STACK_MODEL_LARGE)
3842           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3843         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3844       }
3845     }
3846
3847     _G.useWreg = 0;
3848
3849     if (IFFUNC_ISISR(sym->type)) {
3850       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3851       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3852       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3853       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3854
3855       if(!FUNC_ISSHADOWREGS(sym->type)) {
3856         /* do not restore interrupt vector for WREG,STATUS,BSR
3857          * for high priority interrupt, see genFunction */
3858         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3859         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3860         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3861       }
3862 //      _G.interruptvector = 0;         /* sanity check */
3863
3864
3865       /* if debug then send end of function */
3866 /*      if (options.debug && currFunc)  */
3867       if (currFunc) {
3868         debugFile->writeEndFunction (currFunc, ic, 1);
3869       }
3870         
3871       if(_G.usefastretfie)
3872         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3873       else
3874         pic16_emitpcodeNULLop(POC_RETFIE);
3875
3876       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3877       
3878       _G.usefastretfie = 0;
3879       return;
3880     }
3881
3882     if (IFFUNC_ISCRITICAL(sym->type)) {
3883       pic16_emitcode("setb","ea");
3884     }
3885
3886     /* if debug then send end of function */
3887     if (currFunc) {
3888       debugFile->writeEndFunction (currFunc, ic, 1);
3889     }
3890
3891     /* insert code to restore stack frame, if user enabled it
3892      * and function is not main() */
3893          
3894
3895     pic16_emitpcodeNULLop(POC_RETURN);
3896
3897     /* Mark the end of a function */
3898     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3899 }
3900
3901
3902 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3903 {
3904   unsigned long lit=1;
3905  
3906   // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3907   if(AOP_TYPE(op) == AOP_LIT) {
3908     if(!IS_FLOAT(operandType( op ))) {
3909       lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3910     } else {
3911       union {
3912         unsigned long lit_int;
3913         float lit_float;
3914       } info;
3915         
3916       /* take care if literal is a float */
3917       info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3918       lit = info.lit_int;
3919     }
3920   }
3921
3922   if(is_LitOp(op)) {
3923       if(lit == 0) {
3924         pic16_emitpcode(POC_CLRF, dest);
3925       } else {
3926         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3927         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3928       }
3929   } else {
3930     if(dest->type == PO_WREG && (offset == 0)) {
3931       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3932       return;
3933     }
3934     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3935   }
3936 }
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genRet - generate code for return statement                     */
3940 /*-----------------------------------------------------------------*/
3941 static void genRet (iCode *ic)
3942 {
3943   int size;
3944   operand *left;
3945
3946     FENTRY;
3947         /* if we have no return value then
3948          * just generate the "ret" */
3949         
3950         if (!IC_LEFT(ic)) 
3951                 goto jumpret;       
3952     
3953         /* we have something to return then
3954          * move the return value into place */
3955         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3956         size = AOP_SIZE(IC_LEFT(ic));
3957
3958         if(size <= 4) {
3959                 if(size>3) {
3960                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3961 //                      pic16_emitpcode(POC_MOVFF,
3962 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3963                 }
3964                 if(size>2) {
3965                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3966 //                      pic16_emitpcode(POC_MOVFF,
3967 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3968                 }
3969                 if(size>1) {
3970                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3971 //                      pic16_emitpcode(POC_MOVFF,
3972 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3973                 }
3974
3975 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3976
3977                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3978 //              pic16_emitpcode(POC_MOVFF,
3979 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3980
3981         } else {
3982                 /* >32-bits, setup stack and FSR0 */
3983                 while (size--) {
3984 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3985 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3986
3987                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3988
3989 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3990                         GpsuedoStkPtr++;
3991                 }
3992                         
3993                 /* setup FSR0 */
3994                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3996
3997                 if(STACK_MODEL_LARGE) {
3998                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3999                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4000                 } else {
4001                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4002                 }
4003         }
4004                                 
4005 #if 0
4006         /* old code, left here for reference -- VR */    
4007         while (size--) {
4008           char *l ;
4009
4010                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4011                         /* #NOCHANGE */
4012                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4013                         pic16_emitpcomment("push %s",l);
4014                         pushed++;
4015                 } else {
4016                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4017                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4018                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4019                         
4020                         if (strcmp(fReturn[offset],l)) {
4021                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4022                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4023                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4024                                 } else {
4025                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4026                                 }
4027                                 
4028                                 if(size) {
4029                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4030                                 }
4031                                 offset++;
4032                         }
4033                 }
4034         }    
4035
4036         if (pushed) {
4037                 while(pushed) {
4038                         pushed--;
4039                         if (strcmp(fReturn[pushed],"a"))
4040                                 pic16_emitcode("pop",fReturn[pushed]);
4041                         else
4042                                 pic16_emitcode("pop","acc");
4043                 }
4044         }
4045 #endif
4046
4047
4048         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4049     
4050 jumpret:
4051         /* generate a jump to the return label
4052          * if the next is not the return statement */
4053         if (!(ic->next && ic->next->op == LABEL
4054                 && IC_LABEL(ic->next) == returnLabel)) {
4055         
4056                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4057                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4058         }
4059 }
4060
4061 /*-----------------------------------------------------------------*/
4062 /* genLabel - generates a label                                    */
4063 /*-----------------------------------------------------------------*/
4064 static void genLabel (iCode *ic)
4065 {
4066   FENTRY;
4067
4068   /* special case never generate */
4069   if (IC_LABEL(ic) == entryLabel)
4070     return ;
4071
4072   pic16_emitpLabel(IC_LABEL(ic)->key);
4073 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4074 }
4075
4076 /*-----------------------------------------------------------------*/
4077 /* genGoto - generates a goto                                      */
4078 /*-----------------------------------------------------------------*/
4079 //tsd
4080 static void genGoto (iCode *ic)
4081 {
4082   FENTRY;
4083   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4084 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4085 }
4086
4087
4088 /*-----------------------------------------------------------------*/
4089 /* genMultbits :- multiplication of bits                           */
4090 /*-----------------------------------------------------------------*/
4091 static void genMultbits (operand *left, 
4092                          operand *right, 
4093                          operand *result)
4094 {
4095   FENTRY;
4096
4097   if(!pic16_sameRegs(AOP(result),AOP(right)))
4098     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4099
4100   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4101   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4102   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4103
4104 }
4105
4106
4107 /*-----------------------------------------------------------------*/
4108 /* genMultOneByte : 8 bit multiplication & division                */
4109 /*-----------------------------------------------------------------*/
4110 static void genMultOneByte (operand *left,
4111                             operand *right,
4112                             operand *result)
4113 {
4114
4115   FENTRY;
4116   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4117   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4118
4119   /* (if two literals, the value is computed before) */
4120   /* if one literal, literal on the right */
4121   if (AOP_TYPE(left) == AOP_LIT){
4122     operand *t = right;
4123     right = left;
4124     left = t;
4125   }
4126
4127         /* size is already checked in genMult == 1 */
4128 //      size = AOP_SIZE(result);
4129
4130         if (AOP_TYPE(right) == AOP_LIT){
4131                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4132                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4133                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4134                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4135         } else {
4136                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4137                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4138                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4139                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4140         }
4141         
4142         pic16_genMult8X8_8 (left, right,result);
4143 }
4144
4145 /*-----------------------------------------------------------------*/
4146 /* genMultOneWord : 16 bit multiplication                          */
4147 /*-----------------------------------------------------------------*/
4148 static void genMultOneWord (operand *left,
4149                             operand *right,
4150                             operand *result)
4151 {
4152   FENTRY;
4153   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4154   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4155
4156   /* (if two literals, the value is computed before)
4157    * if one literal, literal on the right */
4158   if (AOP_TYPE(left) == AOP_LIT){
4159     operand *t = right;
4160     right = left;
4161     left = t;
4162   }
4163
4164   /* size is checked already == 2 */
4165 //  size = AOP_SIZE(result);
4166
4167   if (AOP_TYPE(right) == AOP_LIT) {
4168     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4169       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4170       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4171       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4172   } else {
4173     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4174       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4175       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4176       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4177   }
4178         
4179   pic16_genMult16X16_16(left, right,result);
4180 }
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genMultOneLong : 32 bit multiplication                          */
4184 /*-----------------------------------------------------------------*/
4185 static void genMultOneLong (operand *left,
4186                             operand *right,
4187                             operand *result)
4188 {
4189   FENTRY;
4190   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4192
4193   /* (if two literals, the value is computed before)
4194    * if one literal, literal on the right */
4195   if (AOP_TYPE(left) == AOP_LIT){
4196     operand *t = right;
4197     right = left;
4198     left = t;
4199   }
4200
4201   /* size is checked already == 4 */
4202 //  size = AOP_SIZE(result);
4203
4204   if (AOP_TYPE(right) == AOP_LIT) {
4205     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4206         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4207         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4208         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4209   } else {
4210     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4211         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4212         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4213         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214   }
4215         
4216   pic16_genMult32X32_32(left, right,result);
4217 }
4218
4219
4220
4221 /*-----------------------------------------------------------------*/
4222 /* genMult - generates code for multiplication                     */
4223 /*-----------------------------------------------------------------*/
4224 static void genMult (iCode *ic)
4225 {
4226   operand *left = IC_LEFT(ic);
4227   operand *right = IC_RIGHT(ic);
4228   operand *result= IC_RESULT(ic);   
4229
4230     FENTRY;
4231         /* assign the amsops */
4232         pic16_aopOp (left,ic,FALSE);
4233         pic16_aopOp (right,ic,FALSE);
4234         pic16_aopOp (result,ic,TRUE);
4235
4236         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4237
4238         /* special cases first *
4239         * both are bits */
4240         if (AOP_TYPE(left) == AOP_CRY
4241                 && AOP_TYPE(right)== AOP_CRY) {
4242                 genMultbits(left,right,result);
4243           goto release ;
4244         }
4245
4246         /* if both are of size == 1 */
4247         if(AOP_SIZE(left) == 1
4248                 && AOP_SIZE(right) == 1) {
4249                 genMultOneByte(left,right,result);
4250           goto release ;
4251         }
4252
4253         /* if both are of size == 2 */
4254         if(AOP_SIZE(left) == 2
4255                 && AOP_SIZE(right) == 2) {
4256                 genMultOneWord(left, right, result);
4257           goto release;
4258         }
4259         
4260         /* if both are of size == 4 */
4261         if(AOP_SIZE(left) == 4
4262                 && AOP_SIZE(right) == 4) {
4263                 genMultOneLong(left, right, result);
4264           goto release;
4265         }
4266         
4267         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4268
4269
4270         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4271         /* should have been converted to function call */
4272         assert(0) ;
4273
4274 release :
4275         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4276         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4277         pic16_freeAsmop(result,NULL,ic,TRUE); 
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* genDivbits :- division of bits                                  */
4282 /*-----------------------------------------------------------------*/
4283 static void genDivbits (operand *left, 
4284                         operand *right, 
4285                         operand *result)
4286 {
4287   char *l;
4288
4289     FENTRY;
4290     /* the result must be bit */    
4291     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4292     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4293
4294     MOVA(l);    
4295
4296     pic16_emitcode("div","ab");
4297     pic16_emitcode("rrc","a");
4298     pic16_aopPut(AOP(result),"c",0);
4299 }
4300
4301 /*-----------------------------------------------------------------*/
4302 /* genDivOneByte : 8 bit division                                  */
4303 /*-----------------------------------------------------------------*/
4304 static void genDivOneByte (operand *left,
4305                            operand *right,
4306                            operand *result)
4307 {
4308   sym_link *opetype = operandType(result);
4309   char *l ;
4310   symbol *lbl ;
4311   int size,offset;
4312
4313         /* result = divident / divisor
4314          * - divident may be a register or a literal,
4315          * - divisor may be a register or a literal,
4316          * so there are 3 cases (literal / literal is optimized
4317          * by the front-end) to handle.
4318          * In addition we must handle signed and unsigned, which
4319          * result in 6 final different cases -- VR */
4320
4321     FENTRY;
4322     
4323     size = AOP_SIZE(result) - 1;
4324     offset = 1;
4325     /* signed or unsigned */
4326     if (SPEC_USIGN(opetype)) {
4327       pCodeOp *pct1,    /* count */
4328                 *pct2,  /* reste */
4329                 *pct3;  /* temp */
4330       symbol *label1, *label2, *label3;;
4331
4332
4333         /* unsigned is easy */
4334
4335         pct1 = pic16_popGetTempReg(1);
4336         pct2 = pic16_popGetTempReg(1);
4337         pct3 = pic16_popGetTempReg(1);
4338         
4339         label1 = newiTempLabel(NULL);
4340         label2 = newiTempLabel(NULL);
4341         label3 = newiTempLabel(NULL);
4342
4343         /* the following algorithm is extracted from divuint.c */
4344
4345         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4346         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4347         
4348         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4349
4350         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4351         
4352         pic16_emitpLabel(label1->key);
4353         
4354         emitCLRC;
4355         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4356
4357
4358         emitCLRC;
4359         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4360         
4361
4362         emitSKPNC;
4363         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4364         
4365         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4366         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4367         
4368         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4369         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4370         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4371         
4372         pic16_emitpLabel( label3->key );
4373         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4374         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4375         
4376         
4377
4378         pic16_emitpLabel(label2->key);
4379         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4380         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4381         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4382         
4383         /* result is in wreg */
4384         if(AOP_TYPE(result) != AOP_ACC)
4385                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4386
4387         pic16_popReleaseTempReg( pct3, 1);
4388         pic16_popReleaseTempReg( pct2, 1);
4389         pic16_popReleaseTempReg( pct1, 1);
4390
4391         return ;
4392     }
4393
4394     /* signed is a little bit more difficult */
4395
4396     /* save the signs of the operands */
4397     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4398     MOVA(l);    
4399     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4400     pic16_emitcode("push","acc"); /* save it on the stack */
4401
4402     /* now sign adjust for both left & right */
4403     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4404     MOVA(l);       
4405     lbl = newiTempLabel(NULL);
4406     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4407     pic16_emitcode("cpl","a");   
4408     pic16_emitcode("inc","a");
4409     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4410     pic16_emitcode("mov","b,a");
4411
4412     /* sign adjust left side */
4413     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4414     MOVA(l);
4415
4416     lbl = newiTempLabel(NULL);
4417     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4418     pic16_emitcode("cpl","a");
4419     pic16_emitcode("inc","a");
4420     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4421
4422     /* now the division */
4423     pic16_emitcode("div","ab");
4424     /* we are interested in the lower order
4425     only */
4426     pic16_emitcode("mov","b,a");
4427     lbl = newiTempLabel(NULL);
4428     pic16_emitcode("pop","acc");   
4429     /* if there was an over flow we don't 
4430     adjust the sign of the result */
4431     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4432     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4433     CLRC;
4434     pic16_emitcode("clr","a");
4435     pic16_emitcode("subb","a,b");
4436     pic16_emitcode("mov","b,a");
4437     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4438
4439     /* now we are done */
4440     pic16_aopPut(AOP(result),"b",0);
4441     if(size > 0){
4442         pic16_emitcode("mov","c,b.7");
4443         pic16_emitcode("subb","a,acc");   
4444     }
4445     while (size--)
4446         pic16_aopPut(AOP(result),"a",offset++);
4447
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genDiv - generates code for division                            */
4452 /*-----------------------------------------------------------------*/
4453 static void genDiv (iCode *ic)
4454 {
4455     operand *left = IC_LEFT(ic);
4456     operand *right = IC_RIGHT(ic);
4457     operand *result= IC_RESULT(ic);   
4458
4459
4460         /* Division is a very lengthy algorithm, so it is better
4461          * to call support routines than inlining algorithm.
4462          * Division functions written here just in case someone
4463          * wants to inline and not use the support libraries -- VR */
4464
4465     FENTRY;
4466     
4467     /* assign the amsops */
4468     pic16_aopOp (left,ic,FALSE);
4469     pic16_aopOp (right,ic,FALSE);
4470     pic16_aopOp (result,ic,TRUE);
4471
4472     /* special cases first */
4473     /* both are bits */
4474     if (AOP_TYPE(left) == AOP_CRY &&
4475         AOP_TYPE(right)== AOP_CRY) {
4476         genDivbits(left,right,result);
4477         goto release ;
4478     }
4479
4480     /* if both are of size == 1 */
4481     if (AOP_SIZE(left) == 1 &&
4482         AOP_SIZE(right) == 1 ) {
4483         genDivOneByte(left,right,result);
4484         goto release ;
4485     }
4486
4487     /* should have been converted to function call */
4488     assert(0);
4489 release :
4490     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4491     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492     pic16_freeAsmop(result,NULL,ic,TRUE); 
4493 }
4494
4495 /*-----------------------------------------------------------------*/
4496 /* genModbits :- modulus of bits                                   */
4497 /*-----------------------------------------------------------------*/
4498 static void genModbits (operand *left, 
4499                         operand *right, 
4500                         operand *result)
4501 {
4502   char *l;
4503
4504     FENTRY;  
4505     
4506     werror(W_POSSBUG2, __FILE__, __LINE__);
4507     /* the result must be bit */    
4508     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4509     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4510
4511     MOVA(l);       
4512
4513     pic16_emitcode("div","ab");
4514     pic16_emitcode("mov","a,b");
4515     pic16_emitcode("rrc","a");
4516     pic16_aopPut(AOP(result),"c",0);
4517 }
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genModOneByte : 8 bit modulus                                   */
4521 /*-----------------------------------------------------------------*/
4522 static void genModOneByte (operand *left,
4523                            operand *right,
4524                            operand *result)
4525 {
4526   sym_link *opetype = operandType(result);
4527   char *l ;
4528   symbol *lbl ;
4529
4530     FENTRY;
4531     werror(W_POSSBUG2, __FILE__, __LINE__);
4532
4533     /* signed or unsigned */
4534     if (SPEC_USIGN(opetype)) {
4535         /* unsigned is easy */
4536         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4537         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4538         MOVA(l);    
4539         pic16_emitcode("div","ab");
4540         pic16_aopPut(AOP(result),"b",0);
4541         return ;
4542     }
4543
4544     /* signed is a little bit more difficult */
4545
4546     /* save the signs of the operands */
4547     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4548     MOVA(l);
4549
4550     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4551     pic16_emitcode("push","acc"); /* save it on the stack */
4552
4553     /* now sign adjust for both left & right */
4554     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4555     MOVA(l);
4556
4557     lbl = newiTempLabel(NULL);
4558     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4559     pic16_emitcode("cpl","a");   
4560     pic16_emitcode("inc","a");
4561     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4562     pic16_emitcode("mov","b,a"); 
4563
4564     /* sign adjust left side */
4565     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4566     MOVA(l);
4567
4568     lbl = newiTempLabel(NULL);
4569     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4570     pic16_emitcode("cpl","a");   
4571     pic16_emitcode("inc","a");
4572     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4573
4574     /* now the multiplication */
4575     pic16_emitcode("div","ab");
4576     /* we are interested in the lower order
4577     only */
4578     lbl = newiTempLabel(NULL);
4579     pic16_emitcode("pop","acc");   
4580     /* if there was an over flow we don't 
4581     adjust the sign of the result */
4582     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4583     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4584     CLRC ;
4585     pic16_emitcode("clr","a");
4586     pic16_emitcode("subb","a,b");
4587     pic16_emitcode("mov","b,a");
4588     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4589
4590     /* now we are done */
4591     pic16_aopPut(AOP(result),"b",0);
4592
4593 }
4594
4595 /*-----------------------------------------------------------------*/
4596 /* genMod - generates code for division                            */
4597 /*-----------------------------------------------------------------*/
4598 static void genMod (iCode *ic)
4599 {
4600   operand *left = IC_LEFT(ic);
4601   operand *right = IC_RIGHT(ic);
4602   operand *result= IC_RESULT(ic);  
4603
4604     FENTRY;
4605     
4606     /* assign the amsops */
4607     pic16_aopOp (left,ic,FALSE);
4608     pic16_aopOp (right,ic,FALSE);
4609     pic16_aopOp (result,ic,TRUE);
4610
4611     /* special cases first */
4612     /* both are bits */
4613     if (AOP_TYPE(left) == AOP_CRY &&
4614         AOP_TYPE(right)== AOP_CRY) {
4615         genModbits(left,right,result);
4616         goto release ;
4617     }
4618
4619     /* if both are of size == 1 */
4620     if (AOP_SIZE(left) == 1 &&
4621         AOP_SIZE(right) == 1 ) {
4622         genModOneByte(left,right,result);
4623         goto release ;
4624     }
4625
4626     /* should have been converted to function call */
4627     assert(0);
4628
4629 release :
4630     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4631     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4632     pic16_freeAsmop(result,NULL,ic,TRUE); 
4633 }
4634
4635 /*-----------------------------------------------------------------*/
4636 /* genIfxJump :- will create a jump depending on the ifx           */
4637 /*-----------------------------------------------------------------*/
4638 /*
4639   note: May need to add parameter to indicate when a variable is in bit space.
4640 */
4641 static void genIfxJump (iCode *ic, char *jval)
4642 {
4643   FENTRY;
4644   
4645     /* if true label then we jump if condition
4646     supplied is true */
4647     if ( IC_TRUE(ic) ) {
4648
4649         if(strcmp(jval,"a") == 0)
4650           emitSKPZ;
4651         else if (strcmp(jval,"c") == 0)
4652           emitSKPNC;
4653         else {
4654           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4655           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4656         }
4657
4658         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4659         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4660
4661     }
4662     else {
4663         /* false label is present */
4664         if(strcmp(jval,"a") == 0)
4665           emitSKPNZ;
4666         else if (strcmp(jval,"c") == 0)
4667           emitSKPC;
4668         else {
4669           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4670           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4671         }
4672
4673         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4674         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4675
4676     }
4677
4678
4679     /* mark the icode as generated */
4680     ic->generated = 1;
4681 }
4682
4683 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4684 {
4685   FENTRY;
4686   
4687     /* if true label then we jump if condition
4688     supplied is true */
4689     if ( IC_TRUE(ic) ) {
4690       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4691       pic16_emitpcode(POC_BTFSC, jop);
4692
4693       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4694       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4695
4696     } else {
4697       /* false label is present */
4698       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4699       pic16_emitpcode(POC_BTFSS, jop);
4700           
4701       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4702       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4703     }
4704
4705
4706     /* mark the icode as generated */
4707     ic->generated = 1;
4708 }
4709
4710 #if 0
4711 // not needed ATM
4712
4713 /*-----------------------------------------------------------------*/
4714 /* genSkip                                                         */
4715 /*-----------------------------------------------------------------*/
4716 static void genSkip(iCode *ifx,int status_bit)
4717 {
4718   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4719   if(!ifx)
4720     return;
4721
4722   if ( IC_TRUE(ifx) ) {
4723     switch(status_bit) {
4724     case 'z':
4725       emitSKPNZ;
4726       break;
4727
4728     case 'c':
4729       emitSKPNC;
4730       break;
4731
4732     case 'd':
4733       emitSKPDC;
4734       break;
4735
4736     }
4737
4738     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4739     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4740
4741   } else {
4742
4743     switch(status_bit) {
4744
4745     case 'z':
4746       emitSKPZ;
4747       break;
4748
4749     case 'c':
4750       emitSKPC;
4751       break;
4752
4753     case 'd':
4754       emitSKPDC;
4755       break;
4756     }
4757     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4758     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4759
4760   }
4761
4762 }
4763 #endif
4764
4765 /*-----------------------------------------------------------------*/
4766 /* genSkipc                                                        */
4767 /*-----------------------------------------------------------------*/
4768 static void genSkipc(resolvedIfx *rifx)
4769 {
4770   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4771   
4772   if(!rifx)
4773     return;
4774
4775   if(rifx->condition)
4776     emitSKPC;
4777   else
4778     emitSKPNC;
4779
4780   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4781   rifx->generated = 1;
4782 }
4783
4784 #if !(USE_SIMPLE_GENCMP)
4785 /*-----------------------------------------------------------------*/
4786 /* genSkipz2                                                       */
4787 /*-----------------------------------------------------------------*/
4788 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4789 {
4790   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4791   
4792   if(!rifx)
4793     return;
4794
4795   if( (rifx->condition ^ invert_condition) & 1)
4796     emitSKPZ;
4797   else
4798     emitSKPNZ;
4799
4800   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4801   rifx->generated = 1;
4802 }
4803 #endif
4804
4805 #if 0
4806 /*-----------------------------------------------------------------*/
4807 /* genSkipz                                                        */
4808 /*-----------------------------------------------------------------*/
4809 static void genSkipz(iCode *ifx, int condition)
4810 {
4811   if(!ifx)
4812     return;
4813
4814   if(condition)
4815     emitSKPNZ;
4816   else
4817     emitSKPZ;
4818
4819   if ( IC_TRUE(ifx) )
4820     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4821   else
4822     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4823
4824   if ( IC_TRUE(ifx) )
4825     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4826   else
4827     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4828
4829 }
4830 #endif
4831
4832 #if !(USE_SIMPLE_GENCMP)
4833 /*-----------------------------------------------------------------*/
4834 /* genSkipCond                                                     */
4835 /*-----------------------------------------------------------------*/
4836 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4837 {
4838   if(!rifx)
4839     return;
4840
4841   if(rifx->condition)
4842     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4843   else
4844     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4845
4846
4847   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4848   rifx->generated = 1;
4849 }
4850 #endif
4851
4852 #if 0
4853 /*-----------------------------------------------------------------*/
4854 /* genChkZeroes :- greater or less than comparison                 */
4855 /*     For each byte in a literal that is zero, inclusive or the   */
4856 /*     the corresponding byte in the operand with W                */
4857 /*     returns true if any of the bytes are zero                   */
4858 /*-----------------------------------------------------------------*/
4859 static int genChkZeroes(operand *op, int lit,  int size)
4860 {
4861
4862   int i;
4863   int flag =1;
4864
4865   while(size--) {
4866     i = (lit >> (size*8)) & 0xff;
4867
4868     if(i==0) {
4869       if(flag) 
4870         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4871       else
4872         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4873       flag = 0;
4874     }
4875   }
4876
4877   return (flag==0);
4878 }
4879 #endif
4880
4881 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4882 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4883 #endif
4884 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4885 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4886
4887 /*-----------------------------------------------------------------*/
4888 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4889 /*                  aop (if it's NOT a literal) or from lit (if    */
4890 /*                  aop is a literal)                              */
4891 /*-----------------------------------------------------------------*/
4892 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4893   if (aop->type == AOP_LIT) {
4894     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4895   } else {
4896     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4897   }
4898 }
4899
4900 /*-----------------------------------------------------------------*/
4901 /* genCmp :- greater or less than comparison                       */
4902 /*-----------------------------------------------------------------*/
4903
4904 #if USE_SIMPLE_GENCMP
4905
4906 /* genCmp performs a left < right comparison, stores
4907  * the outcome in result (if != NULL) and generates
4908  * control flow code for the ifx (if != NULL).
4909  *
4910  * This version leaves in sequences like
4911  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4912  * which should be optmized by the peephole
4913  * optimizer - RN 2005-01-01 */
4914 static void genCmp (operand *left,operand *right,
4915                     operand *result, iCode *ifx, int sign)
4916 {
4917   resolvedIfx rIfx;
4918   int size;
4919   int offs;
4920   symbol *templbl;
4921   operand *dummy;
4922   unsigned long lit;
4923   unsigned long mask;
4924   int performedLt;
4925
4926   FENTRY;
4927   
4928   assert (AOP_SIZE(left) == AOP_SIZE(right));
4929   assert (left && right);
4930
4931   size = AOP_SIZE(right) - 1;
4932   mask = (0x100UL << (size*8)) - 1;
4933   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4934   performedLt = 1;
4935   templbl = NULL;
4936   lit = 0;
4937   
4938   resolveIfx (&rIfx, ifx);
4939
4940   /**********************************************************************
4941    * handle bits - bit compares are promoted to int compares seemingly! *
4942    **********************************************************************/
4943 #if 0
4944   // THIS IS COMPLETELY UNTESTED!
4945   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4946     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4947     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4948     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4949
4950     emitSETC;
4951     // 1 < {0,1} is false --> clear C by skipping the next instruction
4952     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4953     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4954     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4955     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4956     emitCLRC; // only skipped for left=0 && right=1
4957
4958     goto correct_result_in_carry;
4959   } // if
4960 #endif
4961
4962   /*************************************************
4963    * make sure that left is register (or the like) *
4964    *************************************************/
4965   if (!isAOP_REGlike(left)) {
4966     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4967     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4968     #endif
4969     assert (isAOP_LIT(left));
4970     assert (isAOP_REGlike(right));
4971     // swap left and right
4972     // left < right <==> right > left <==> (right >= left + 1)
4973     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4974
4975     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4976       // MAXVALUE < right? always false
4977       if (performedLt) emitCLRC; else emitSETC;
4978       goto correct_result_in_carry;
4979     } // if
4980
4981     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4982     // that's we handled it above.
4983     lit++;
4984
4985     dummy = left;
4986     left = right;
4987     right = dummy;
4988
4989     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4990   } else if (isAOP_LIT(right)) {
4991     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4992   } // if
4993
4994   assert (isAOP_REGlike(left)); // left must be register or the like
4995   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4996
4997   /*************************************************
4998    * special cases go here                         *
4999    *************************************************/
5000
5001   if (isAOP_LIT(right)) {
5002     if (!sign) {
5003       // unsigned comparison to a literal
5004       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5005       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5006       #endif
5007       if (lit == 0) {
5008         // unsigned left < 0? always false
5009         if (performedLt) emitCLRC; else emitSETC;
5010         goto correct_result_in_carry;
5011       }
5012     } else {
5013       // signed comparison to a literal
5014       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5015       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5016       #endif
5017       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5018         // signed left < 0x80000000? always false
5019         if (performedLt) emitCLRC; else emitSETC;
5020         goto correct_result_in_carry;
5021       } else if (lit == 0) {
5022         // compare left < 0; set CARRY if SIGNBIT(left) is set
5023         if (performedLt) emitSETC; else emitCLRC;
5024         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5025         if (performedLt) emitCLRC; else emitSETC;
5026         goto correct_result_in_carry;
5027       }
5028     } // if (!sign)
5029   } // right is literal
5030
5031   /*************************************************
5032    * perform a general case comparison             *
5033    * make sure we get CARRY==1 <==> left >= right  *
5034    *************************************************/
5035   // compare most significant bytes
5036   //DEBUGpc ("comparing bytes at offset %d", size);
5037   if (!sign) {
5038     // unsigned comparison
5039     mov2w_regOrLit (AOP(right), lit, size);
5040     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5041   } else {
5042     // signed comparison
5043     // (add 2^n to both operands then perform an unsigned comparison)
5044     if (isAOP_LIT(right)) {
5045       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5046       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5047
5048       if (litbyte == 0x80) {
5049         // left >= 0x80 -- always true, but more bytes to come
5050         pic16_mov2w (AOP(left), size);
5051         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5052         emitSETC;
5053       } else {
5054         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5055         pic16_mov2w (AOP(left), size);
5056         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5057         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5058       } // if
5059     } else {
5060       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5061       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5062       pic16_mov2w (AOP(left), size);
5063       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5064       pic16_emitpcode (POC_MOVWF, pctemp);
5065       pic16_mov2w (AOP(right), size);
5066       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5067       pic16_emitpcode (POC_SUBFW, pctemp);
5068       //pic16_popReleaseTempReg(pctemp, 1);
5069     }
5070   } // if (!sign)
5071
5072   // compare remaining bytes (treat as unsigned case from above)
5073   templbl = newiTempLabel ( NULL );
5074   offs = size;
5075   while (offs--) {
5076     //DEBUGpc ("comparing bytes at offset %d", offs);
5077     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5078     mov2w_regOrLit (AOP(right), lit, offs);
5079     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5080   } // while (offs)
5081   pic16_emitpLabel (templbl->key);
5082   goto result_in_carry;
5083
5084 result_in_carry:
5085   
5086   /****************************************************
5087    * now CARRY contains the result of the comparison: *
5088    * SUBWF sets CARRY iff                             *
5089    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5090    * (F=left, W=right)
5091    ****************************************************/
5092
5093   if (performedLt) {
5094     if (result && AOP_TYPE(result) != AOP_CRY) {
5095       // value will be stored
5096       emitTOGC;
5097     } else {
5098       // value wil only be used in the following genSkipc()
5099       rIfx.condition ^= 1;
5100     }
5101   } // if
5102
5103 correct_result_in_carry:
5104
5105   // assign result to variable (if neccessary)
5106   if (result && AOP_TYPE(result) != AOP_CRY) {
5107     //DEBUGpc ("assign result");
5108     size = AOP_SIZE(result);
5109     while (size--) {
5110       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5111     } // while
5112     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5113   } // if (result)
5114
5115   // perform conditional jump
5116   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5117   if (ifx) {
5118     //DEBUGpc ("generate control flow");
5119     rIfx.condition ^= 1;
5120     genSkipc (&rIfx);
5121     ifx->generated = 1;
5122   } // if
5123 }
5124
5125 #elif 1
5126                 /* { */
5127       /* original code */
5128 static void genCmp (operand *left,operand *right,
5129                     operand *result, iCode *ifx, int sign)
5130 {
5131   int size; //, offset = 0 ;
5132   unsigned long lit = 0L,i = 0;
5133   resolvedIfx rFalseIfx;
5134   //  resolvedIfx rTrueIfx;
5135   symbol *truelbl;
5136   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5137 /*
5138   if(ifx) {
5139     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5140     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5141   }
5142 */
5143
5144   FENTRY;
5145   
5146   resolveIfx(&rFalseIfx,ifx);
5147   truelbl  = newiTempLabel(NULL);
5148   size = max(AOP_SIZE(left),AOP_SIZE(right));
5149
5150   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5151
5152 #define _swapp
5153
5154   /* if literal is on the right then swap with left */
5155   if ((AOP_TYPE(right) == AOP_LIT)) {
5156     operand *tmp = right ;
5157     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5158     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5159 #ifdef _swapp
5160
5161     lit = (lit - 1) & mask;
5162     right = left;
5163     left = tmp;
5164     rFalseIfx.condition ^= 1;
5165 #endif
5166
5167   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5168     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5169   }
5170
5171
5172   //if(IC_TRUE(ifx) == NULL)
5173   /* if left & right are bit variables */
5174   if (AOP_TYPE(left) == AOP_CRY &&
5175       AOP_TYPE(right) == AOP_CRY ) {
5176     assert (0 && "bit variables used in genCmp");
5177     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5178     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5179   } else {
5180     /* subtract right from left if at the
5181        end the carry flag is set then we know that
5182        left is greater than right */
5183
5184     symbol *lbl  = newiTempLabel(NULL);
5185
5186 #if 0
5187         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5188                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5189 #endif
5190
5191 #ifndef _swapp
5192     if(AOP_TYPE(right) == AOP_LIT) {
5193
5194       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5195
5196       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5197
5198       /* special cases */
5199
5200       if(lit == 0) {
5201
5202         if(sign != 0) 
5203           genSkipCond(&rFalseIfx,left,size-1,7);
5204         else 
5205           /* no need to compare to 0...*/
5206           /* NOTE: this is a de-generate compare that most certainly 
5207            *       creates some dead code. */
5208           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5209
5210         if(ifx) ifx->generated = 1;
5211         return;
5212
5213       }
5214       size--;
5215
5216       if(size == 0) {
5217         //i = (lit >> (size*8)) & 0xff;
5218         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5219         
5220         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5221
5222         i = ((0-lit) & 0xff);
5223         if(sign) {
5224           if( i == 0x81) { 
5225             /* lit is 0x7f, all signed chars are less than
5226              * this except for 0x7f itself */
5227             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5228             genSkipz2(&rFalseIfx,0);
5229           } else {
5230             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5231             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5232             genSkipc(&rFalseIfx);
5233           }
5234
5235         } else {
5236           if(lit == 1) {
5237             genSkipz2(&rFalseIfx,1);
5238           } else {
5239             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5240             genSkipc(&rFalseIfx);
5241           }
5242         }
5243
5244         if(ifx) ifx->generated = 1;
5245         return;
5246       }
5247
5248       /* chars are out of the way. now do ints and longs */
5249
5250
5251       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5252         
5253       /* special cases */
5254
5255       if(sign) {
5256
5257         if(lit == 0) {
5258           genSkipCond(&rFalseIfx,left,size,7);
5259           if(ifx) ifx->generated = 1;
5260           return;
5261         }
5262
5263         if(lit <0x100) {
5264           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5265
5266           //rFalseIfx.condition ^= 1;
5267           //genSkipCond(&rFalseIfx,left,size,7);
5268           //rFalseIfx.condition ^= 1;
5269
5270           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5271           if(rFalseIfx.condition)
5272             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5273           else
5274             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5275
5276           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5277           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5278           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5279
5280           while(size > 1)
5281             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5282
5283           if(rFalseIfx.condition) {
5284             emitSKPZ;
5285             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5286
5287           } else {
5288             emitSKPNZ;
5289           }
5290
5291           genSkipc(&rFalseIfx);
5292           pic16_emitpLabel(truelbl->key);
5293           if(ifx) ifx->generated = 1;
5294           return;
5295
5296         }
5297
5298         if(size == 1) {
5299
5300           if( (lit & 0xff) == 0) {
5301             /* lower byte is zero */
5302             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5303             i = ((lit >> 8) & 0xff) ^0x80;
5304             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5305             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5306             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5307             genSkipc(&rFalseIfx);
5308
5309
5310             if(ifx) ifx->generated = 1;
5311             return;
5312
5313           }
5314         } else {
5315           /* Special cases for signed longs */
5316           if( (lit & 0xffffff) == 0) {
5317             /* lower byte is zero */
5318             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5319             i = ((lit >> 8*3) & 0xff) ^0x80;
5320             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5321             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5322             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5323             genSkipc(&rFalseIfx);
5324
5325
5326             if(ifx) ifx->generated = 1;
5327             return;
5328
5329           }
5330
5331         }
5332
5333
5334         if(lit & (0x80 << (size*8))) {
5335           /* lit is negative */
5336           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5337
5338           //genSkipCond(&rFalseIfx,left,size,7);
5339
5340           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5341
5342           if(rFalseIfx.condition)
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344           else
5345             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5346
5347
5348         } else {
5349           /* lit is positive */
5350           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5351           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5352           if(rFalseIfx.condition)
5353             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5354           else
5355             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5356
5357         }
5358
5359         /*
5360           This works, but is only good for ints.
5361           It also requires a "known zero" register.
5362           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5363           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5364           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5365           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5366           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5367           genSkipc(&rFalseIfx);
5368
5369           pic16_emitpLabel(truelbl->key);
5370           if(ifx) ifx->generated = 1;
5371           return;
5372         **/
5373           
5374         /* There are no more special cases, so perform a general compare */
5375   
5376         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5377         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5378
5379         while(size--) {
5380
5381           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5382           emitSKPNZ;
5383           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5384         }
5385         //rFalseIfx.condition ^= 1;
5386         genSkipc(&rFalseIfx);
5387
5388         pic16_emitpLabel(truelbl->key);
5389
5390         if(ifx) ifx->generated = 1;
5391         return;
5392
5393
5394       }
5395
5396
5397       /* sign is out of the way. So now do an unsigned compare */
5398       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5399
5400
5401       /* General case - compare to an unsigned literal on the right.*/
5402
5403       i = (lit >> (size*8)) & 0xff;
5404       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5405       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5406       while(size--) {
5407         i = (lit >> (size*8)) & 0xff;
5408
5409         if(i) {
5410           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5411           emitSKPNZ;
5412           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5413         } else {
5414           /* this byte of the lit is zero, 
5415            *if it's not the last then OR in the variable */
5416           if(size)
5417             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5418         }
5419       }
5420
5421
5422       pic16_emitpLabel(lbl->key);
5423 //      pic16_emitpLabel(truelbl->key);
5424       //if(emitFinalCheck)
5425       genSkipc(&rFalseIfx);
5426       if(sign)
5427         pic16_emitpLabel(truelbl->key);
5428
5429       if(ifx) ifx->generated = 1;
5430       return;
5431
5432
5433     }
5434 #endif  // _swapp
5435
5436     if(AOP_TYPE(left) == AOP_LIT) {
5437       //symbol *lbl = newiTempLabel(NULL);
5438
5439       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5440
5441
5442       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5443
5444       /* Special cases */
5445       if((lit == 0) && (sign == 0)){
5446
5447         size--;
5448         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5449         while(size) 
5450           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5451
5452         genSkipz2(&rFalseIfx,0);
5453         if(ifx) ifx->generated = 1;
5454         return;
5455       }
5456
5457       if(size==1) {
5458         /* Special cases */
5459         lit &= 0xff;
5460         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5461           /* degenerate compare can never be true */
5462           if(rFalseIfx.condition == 0)
5463             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5464
5465           if(ifx) ifx->generated = 1;
5466           return;
5467         }
5468
5469         if(sign) {
5470           /* signed comparisons to a literal byte */
5471
5472           int lp1 = (lit+1) & 0xff;
5473
5474           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5475           switch (lp1) {
5476           case 0:
5477             rFalseIfx.condition ^= 1;
5478             genSkipCond(&rFalseIfx,right,0,7);
5479             break;
5480           case 0x7f:
5481             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5482             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5483             genSkipz2(&rFalseIfx,1);
5484             break;
5485           default:
5486             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5487             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5488             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5489             rFalseIfx.condition ^= 1;
5490             genSkipc(&rFalseIfx);
5491             break;
5492           }
5493         } else {
5494           /* unsigned comparisons to a literal byte */
5495
5496           switch(lit & 0xff ) {
5497           case 0:
5498             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5499             genSkipz2(&rFalseIfx,0);
5500             break;
5501           case 0x7f:
5502             rFalseIfx.condition ^= 1;
5503             genSkipCond(&rFalseIfx,right,0,7);
5504             break;
5505
5506           default:
5507             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5508             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5509             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5510             rFalseIfx.condition ^= 1;
5511             if (AOP_TYPE(result) == AOP_CRY)
5512               genSkipc(&rFalseIfx);
5513             else {
5514               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5515               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5516             }         
5517             break;
5518           }
5519         }
5520
5521         if(ifx) ifx->generated = 1;
5522         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5523                 goto check_carry;
5524         return;
5525
5526       } else {
5527
5528         /* Size is greater than 1 */
5529
5530         if(sign) {
5531           int lp1 = lit+1;
5532
5533           size--;
5534
5535           if(lp1 == 0) {
5536             /* this means lit = 0xffffffff, or -1 */
5537
5538
5539             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5540             rFalseIfx.condition ^= 1;
5541             genSkipCond(&rFalseIfx,right,size,7);
5542             if(ifx) ifx->generated = 1;
5543
5544             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5545               goto check_carry;
5546
5547             return;
5548           }
5549
5550           if(lit == 0) {
5551             int s = size;
5552
5553             if(rFalseIfx.condition) {
5554               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5555               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5556             }
5557
5558             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5559             while(size--)
5560               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5561
5562
5563             emitSKPZ;
5564             if(rFalseIfx.condition) {
5565               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5566               pic16_emitpLabel(truelbl->key);
5567             }else {
5568               rFalseIfx.condition ^= 1;
5569               genSkipCond(&rFalseIfx,right,s,7);
5570             }
5571
5572             if(ifx) ifx->generated = 1;
5573
5574             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5575               goto check_carry;
5576
5577             return;
5578           }
5579
5580           if((size == 1) &&  (0 == (lp1&0xff))) {
5581             /* lower byte of signed word is zero */
5582             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5583             i = ((lp1 >> 8) & 0xff) ^0x80;
5584             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5585             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5586             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5587
5588             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5589               emitTOGC;
5590               if(ifx) ifx->generated = 1;
5591               goto check_carry;
5592             } else {
5593               rFalseIfx.condition ^= 1;
5594               genSkipc(&rFalseIfx);
5595               if(ifx) ifx->generated = 1;
5596             }
5597
5598             return;
5599           }
5600
5601           if(lit & (0x80 << (size*8))) {
5602             /* Lit is less than zero */
5603             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5604             //rFalseIfx.condition ^= 1;
5605             //genSkipCond(&rFalseIfx,left,size,7);
5606             //rFalseIfx.condition ^= 1;
5607             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5608             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5609
5610             if(rFalseIfx.condition)
5611               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5612             else
5613               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5614
5615
5616           } else {
5617             /* Lit is greater than or equal to zero */
5618             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5619             //rFalseIfx.condition ^= 1;
5620             //genSkipCond(&rFalseIfx,right,size,7);
5621             //rFalseIfx.condition ^= 1;
5622
5623             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5624             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5625
5626             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5627             if(rFalseIfx.condition)
5628               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5629             else
5630               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5631
5632           }
5633
5634           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5635           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5636
5637           while(size--) {
5638
5639             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5640             emitSKPNZ;
5641             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5642           }
5643           rFalseIfx.condition ^= 1;
5644           //rFalseIfx.condition = 1;
5645           genSkipc(&rFalseIfx);
5646
5647           pic16_emitpLabel(truelbl->key);
5648
5649           if(ifx) ifx->generated = 1;
5650
5651
5652           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5653             goto check_carry;
5654
5655           return;
5656           // end of if (sign)
5657         } else {
5658
5659           /* compare word or long to an unsigned literal on the right.*/
5660
5661
5662           size--;
5663           if(lit < 0xff) {
5664             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5665             switch (lit) {
5666             case 0:
5667               break; /* handled above */
5668 /*
5669             case 0xff:
5670               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5671               while(size--)
5672                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5673               genSkipz2(&rFalseIfx,0);
5674               break;
5675 */
5676             default:
5677               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5678               while(--size)
5679                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5680
5681               emitSKPZ;
5682               if(rFalseIfx.condition)
5683                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5684               else
5685                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5686
5687
5688               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5689               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5690
5691               rFalseIfx.condition ^= 1;
5692               genSkipc(&rFalseIfx);
5693             }
5694
5695             pic16_emitpLabel(truelbl->key);
5696
5697             if(ifx) ifx->generated = 1;
5698
5699             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5700               goto check_carry;
5701
5702             return;
5703           }
5704
5705
5706           lit++;
5707           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5708           i = (lit >> (size*8)) & 0xff;
5709
5710           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5711           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5712
5713           while(size--) {
5714             i = (lit >> (size*8)) & 0xff;
5715
5716             if(i) {
5717               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5718               emitSKPNZ;
5719               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5720             } else {
5721               /* this byte of the lit is zero, 
5722                * if it's not the last then OR in the variable */
5723               if(size)
5724                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5725             }
5726           }
5727
5728
5729           pic16_emitpLabel(lbl->key);
5730
5731           rFalseIfx.condition ^= 1;
5732
5733           genSkipc(&rFalseIfx);
5734         }
5735
5736         if(sign)
5737           pic16_emitpLabel(truelbl->key);
5738         if(ifx) ifx->generated = 1;
5739
5740             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5741               goto check_carry;
5742
5743         return;
5744       }
5745     }
5746     /* Compare two variables */
5747
5748     DEBUGpic16_emitcode(";sign","%d",sign);
5749
5750     size--;
5751     if(sign) {
5752       /* Sigh. thus sucks... */
5753       if(size) {
5754         pCodeOp *pctemp;
5755         
5756         pctemp = pic16_popGetTempReg(1);
5757         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5758         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5760         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5761         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5762         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5763         pic16_popReleaseTempReg(pctemp, 1);
5764       } else {
5765         /* Signed char comparison */
5766         /* Special thanks to Nikolai Golovchenko for this snippet */
5767         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5768         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5769         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5770         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5771         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5772         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5773
5774         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5775         genSkipc(&rFalseIfx);
5776           
5777         if(ifx) ifx->generated = 1;
5778
5779             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5780               goto check_carry;
5781
5782         return;
5783       }
5784
5785     } else {
5786
5787       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5788       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5789     }
5790
5791
5792     /* The rest of the bytes of a multi-byte compare */
5793     while (size) {
5794
5795       emitSKPZ;
5796       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5797       size--;
5798
5799       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5800       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5801
5802
5803     }
5804
5805     pic16_emitpLabel(lbl->key);
5806
5807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5808     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5809         (AOP_TYPE(result) == AOP_REG)) {
5810       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5811       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5812     } else {
5813       genSkipc(&rFalseIfx);
5814     }         
5815     //genSkipc(&rFalseIfx);
5816     if(ifx) ifx->generated = 1;
5817
5818
5819             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5820               goto check_carry;
5821
5822     return;
5823
5824   }
5825
5826 check_carry:
5827   if ((AOP_TYPE(result) != AOP_CRY) 
5828         && AOP_SIZE(result)) {
5829     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5830
5831     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5832
5833     pic16_outBitC(result);
5834   } else {
5835     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5836     /* if the result is used in the next
5837        ifx conditional branch then generate
5838        code a little differently */
5839     if (ifx )
5840       genIfxJump (ifx,"c");
5841     else
5842       pic16_outBitC(result);
5843     /* leave the result in acc */
5844   }
5845
5846 }
5847
5848 #else   /* old version of genCmp() */   /* } else { */
5849
5850 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5851 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5852         operand *result, int offset, int invert_op)
5853 {
5854   /* add code here */
5855   
5856   /* check condition, > or < ?? */
5857   if(rIfx->condition != 0)invert_op ^= 1;
5858   
5859   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5860
5861   if(!ifx)invert_op ^= 1;
5862
5863   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5864       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5865   
5866   /* do selection */
5867   if(!invert_op)return POC_CPFSGT;
5868   else return POC_CPFSLT;
5869 }
5870
5871 static int compareAopfirstpass=1;
5872
5873 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5874             operand *oper, int offset, operand *result,
5875             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5876             symbol *tlbl)
5877 {
5878   int op;
5879   symbol *truelbl;
5880
5881   /* invert if there is a result to be loaded, in order to fit,
5882    * SETC/CLRC sequence */
5883   if(AOP_SIZE(result))invert_op ^= 1;
5884
5885 //  if(sign && !offset)invert_op ^= 1;
5886   
5887 //  if(sign)invert_op ^= 1;
5888   
5889   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5890
5891   if(AOP_SIZE(result) && compareAopfirstpass) {
5892     if(!ifx) {
5893       if(pcop2)
5894         pic16_emitpcode(POC_SETF, pcop2);
5895       else
5896         emitSETC;
5897     } else {
5898       if(pcop2)
5899         pic16_emitpcode(POC_CLRF, pcop2);
5900       else
5901         emitCLRC;
5902     }
5903   }
5904
5905   compareAopfirstpass = 0;
5906
5907       /* there is a bug when comparing operands with size > 1,
5908        * because higher bytes can be equal and test should be performed
5909        * to the next lower byte, current algorithm, considers operands
5910        * inequal in these cases! -- VR 20041107 */
5911
5912     
5913   if(pcop)
5914     pic16_emitpcode(op, pcop);
5915   else
5916     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5917
5918
5919   if((!sign || !offset) && AOP_SIZE(result)) {
5920     if(!ifx) {
5921       if(pcop2)
5922         pic16_emitpcode(POC_CLRF, pcop2);
5923         else
5924         emitCLRC;
5925     } else {
5926       if(pcop2)
5927         pic16_emitpcode(POC_SETF, pcop2);
5928       else
5929         emitSETC;
5930     }
5931     
5932     /* don't emit final branch (offset == 0) */
5933     if(offset) {
5934
5935       if(pcop2)
5936         pic16_emitpcode(POC_RRCF, pcop2);
5937
5938       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5939     }
5940   } else {
5941     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5942       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5943             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5944
5945       truelbl = newiTempLabel( NULL );
5946       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5947       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5948         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5949       else
5950         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5951       pic16_emitpLabel(truelbl->key);
5952     } else {
5953       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5954     }
5955   }
5956 }
5957
5958
5959   
5960
5961 #if 1   /* { */
5962 static void genCmp (operand *left, operand *right,
5963                     operand *result, iCode *ifx, int sign)
5964 {
5965   int size, cmpop=1;
5966   long lit = 0L;
5967   resolvedIfx rFalseIfx;
5968   symbol *falselbl, *tlbl;
5969
5970     FENTRY;
5971     
5972     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5973
5974     resolveIfx(&rFalseIfx, ifx);
5975     size = max(AOP_SIZE(left), AOP_SIZE(right));
5976     
5977     /* if left & right are bit variables */
5978     if(AOP_TYPE(left) == AOP_CRY
5979       && AOP_TYPE(right) == AOP_CRY ) {
5980
5981         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5982         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5983         
5984         werror(W_POSSBUG2, __FILE__, __LINE__);
5985         exit(-1);
5986     }
5987     
5988     /* if literal is on the right then swap with left */
5989     if((AOP_TYPE(right) == AOP_LIT)) {
5990       operand *tmp = right ;
5991 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5992
5993         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5994
5995 //      lit = (lit - 1) & mask;
5996         right = left;
5997         left = tmp;
5998         rFalseIfx.condition ^= 1;               /* reverse compare */
5999     } else
6000     if ((AOP_TYPE(left) == AOP_LIT)) {
6001       /* float compares are handled by support functions */
6002       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6003     }
6004
6005     /* actual comparing algorithm */
6006 //    size = AOP_SIZE( right );
6007
6008     falselbl = newiTempLabel( NULL );
6009     if(AOP_TYPE(left) == AOP_LIT) {
6010       /* compare to literal */
6011       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6012       
6013       if(sign) {
6014         pCodeOp *pct, *pct2;
6015         symbol *tlbl1;
6016
6017         /* signed compare */
6018         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6019
6020         pct = pic16_popCopyReg(&pic16_pc_prodl);
6021         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6022         tlbl = newiTempLabel( NULL );
6023         
6024         /* first compare signs:
6025          *  a. if both are positive, compare just like unsigned
6026          *  b. if both are negative, invert cmpop, compare just like unsigned
6027          *  c. if different signs, determine the result directly */
6028
6029         size--;
6030
6031 #if 1
6032         /* { */
6033         tlbl1 = newiTempLabel( NULL );
6034 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6035
6036         if(lit > 0) {
6037
6038           /* literal is zero or positive:
6039            *  a. if carry is zero, too, continue compare,
6040            *  b. if carry is set, then continue depending on cmpop ^ condition:
6041            *    1. '<' return false (literal < variable),
6042            *    2. '>' return true (literal > variable) */
6043 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6044           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6045           
6046           
6047           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6049         } else 
6050         if(lit < 0) {
6051           
6052           /* literal is negative:
6053            *  a. if carry is set, too, continue compare,
6054            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6055            *    1. '<' return true (literal < variable),
6056            *    2. '>' return false (literal > variable) */
6057 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6058           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6059           
6060           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6061           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6062         }
6063 #if 1
6064         else {
6065           /* lit == 0 */
6066           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6067           
6068           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6069           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6070         }
6071 #endif
6072         
6073         
6074         pic16_emitpLabel( tlbl1->key );
6075 #endif  /* } */
6076
6077         compareAopfirstpass=1;
6078 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6079 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6080 //        pic16_emitpcode(POC_MOVWF, pct);
6081
6082 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6083         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6084 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6085         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6086
6087         /* generic case */        
6088           while( size-- ) {
6089 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6090 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6091 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6092 //            pic16_emitpcode(POC_MOVWF, pct);
6093
6094 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6095             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6096             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6097 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6098 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6099           }
6100 //        }
6101         
6102         if(ifx)ifx->generated = 1;
6103
6104         if(AOP_SIZE(result)) {
6105           pic16_emitpLabel(tlbl->key);
6106           pic16_emitpLabel(falselbl->key);
6107           pic16_outBitOp( result, pct2 );
6108         } else {
6109           pic16_emitpLabel(tlbl->key);
6110         }
6111       } else {
6112
6113
6114         /* unsigned compare */      
6115         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6116     
6117         compareAopfirstpass=1;
6118         while(size--) {
6119           
6120           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6121           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6122
6123         }
6124
6125         if(ifx)ifx->generated = 1;
6126
6127
6128         if(AOP_SIZE(result)) {
6129           pic16_emitpLabel(falselbl->key);
6130           pic16_outBitC( result );
6131         }
6132
6133       }
6134     } else {
6135       /* compare registers */
6136       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6137
6138
6139       if(sign) {
6140         pCodeOp *pct, *pct2;
6141         
6142         /* signed compare */
6143         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6144
6145         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6146         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6147         tlbl = newiTempLabel( NULL );
6148         
6149         compareAopfirstpass=1;
6150
6151         size--;
6152         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6153 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6155         pic16_emitpcode(POC_MOVWF, pct);
6156
6157         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6159         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6160
6161         /* WREG already holds left + 0x80 */
6162         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6163         
6164         while( size-- ) {
6165           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6166 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6167           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6168           pic16_emitpcode(POC_MOVWF, pct);
6169                 
6170           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6171 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6172           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6173
6174           /* WREG already holds left + 0x80 */
6175           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6176 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6177         }
6178         
6179         if(ifx)ifx->generated = 1;
6180
6181         if(AOP_SIZE(result)) {
6182           pic16_emitpLabel(tlbl->key);
6183           pic16_emitpLabel(falselbl->key);
6184           pic16_outBitOp( result, pct2 );
6185         } else {
6186           pic16_emitpLabel(tlbl->key);
6187         }
6188
6189       } else {
6190         /* unsigned compare */      
6191         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6192
6193         compareAopfirstpass=1;
6194         while(size--) {
6195           
6196           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6197           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6198
6199         }
6200
6201         if(ifx)ifx->generated = 1;
6202         if(AOP_SIZE(result)) {
6203
6204           pic16_emitpLabel(falselbl->key);
6205           pic16_outBitC( result );
6206         }
6207
6208       }
6209     }
6210 }
6211
6212 #else    /* } else { */
6213
6214 /* new version of genCmp -- VR 20041012 */
6215 static void genCmp (operand *left,operand *right,
6216                     operand *result, iCode *ifx, int sign)
6217 {
6218   int size; //, offset = 0 ;
6219   unsigned long lit = 0L,i = 0;
6220   resolvedIfx rFalseIfx;
6221   int willCheckCarry=0;
6222   //  resolvedIfx rTrueIfx;
6223   symbol *truelbl;
6224
6225     FENTRY;
6226   
6227   /* General concept:
6228    * subtract right from left if at the end the carry flag is set then we
6229    * know that left is greater than right */
6230             
6231   resolveIfx(&rFalseIfx,ifx);
6232   truelbl  = newiTempLabel(NULL);
6233   size = max(AOP_SIZE(left),AOP_SIZE(right));
6234
6235   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6236
6237   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6238    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6239   
6240
6241   /* if literal is on the right then swap with left */
6242   if ((AOP_TYPE(right) == AOP_LIT)) {
6243     operand *tmp = right ;
6244     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6245
6246       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6247
6248 //      lit = (lit - 1) & mask;
6249       right = left;
6250       left = tmp;
6251       rFalseIfx.condition ^= 1;         /* reverse compare */
6252   } else
6253   if ((AOP_TYPE(left) == AOP_LIT)) {
6254     /* float compares are handled by support functions */
6255     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6256   }
6257
6258
6259   //if(IC_TRUE(ifx) == NULL)
6260   /* if left & right are bit variables */
6261   if (AOP_TYPE(left) == AOP_CRY &&
6262       AOP_TYPE(right) == AOP_CRY ) {
6263
6264     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6265     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6266
6267   } else {
6268     symbol *lbl  = newiTempLabel(NULL);
6269
6270     if(AOP_TYPE(left) == AOP_LIT) {
6271       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6272
6273       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6274         willCheckCarry = 1;
6275       else willCheckCarry = 0;
6276
6277       /* Special cases */
6278       if((lit == 0) && (sign == 0)) {
6279         /* unsigned compare to 0 */
6280         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6281         
6282         size--;
6283         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6284         while(size) 
6285           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6286
6287         genSkipz2(&rFalseIfx,0);
6288         if(ifx)ifx->generated = 1;
6289         return;
6290       }
6291
6292       if(size==1) {
6293         /* Special cases */
6294         lit &= 0xff;
6295         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6296           /* degenerate compare can never be true */
6297           if(rFalseIfx.condition == 0)
6298             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6299
6300           if(ifx) ifx->generated = 1;
6301           return;
6302         }
6303
6304         if(sign) {
6305           /* signed comparisons to a literal byte */
6306           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6307
6308           int lp1 = (lit+1) & 0xff;
6309
6310           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6311           switch (lp1) {
6312           case 0:
6313             rFalseIfx.condition ^= 1;
6314             genSkipCond(&rFalseIfx,right,0,7);
6315             break;
6316           case 0x7f:
6317             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6318             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6319             genSkipz2(&rFalseIfx,1);
6320             break;
6321           default:
6322             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6323             
6324             if(rFalseIfx.condition)
6325               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6326             else
6327               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6328
6329             if(willCheckCarry) {
6330               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6331               else { emitSETC; emitCLRC; }
6332               
6333             } else {
6334               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6335             }              
6336                       
6337 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6338             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6339             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6340             rFalseIfx.condition ^= 1;
6341             genSkipc(&rFalseIfx);
6342 */
6343             break;
6344           }
6345         } else {
6346           /* unsigned comparisons to a literal byte */
6347           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6348
6349           switch(lit & 0xff ) {
6350                           /* special cases */
6351           case 0:
6352             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6353             genSkipz2(&rFalseIfx,0);
6354             break;
6355           case 0x7f:
6356             rFalseIfx.condition ^= 1;
6357             genSkipCond(&rFalseIfx,right,0,7);
6358             break;
6359           default:
6360             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6361             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6362             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6363             rFalseIfx.condition ^= 1;
6364             if (AOP_TYPE(result) == AOP_CRY)
6365               genSkipc(&rFalseIfx);
6366             else {
6367               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6368               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6369             }         
6370             break;
6371           }
6372         }
6373
6374         if(ifx) ifx->generated = 1;
6375         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6376                 goto check_carry;
6377         return;
6378
6379       } else {
6380
6381         /* Size is greater than 1 */
6382
6383         if(sign) {
6384           int lp1 = lit+1;
6385
6386           size--;
6387
6388           if(lp1 == 0) {
6389             /* this means lit = 0xffffffff, or -1 */
6390
6391
6392             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6393             rFalseIfx.condition ^= 1;
6394             genSkipCond(&rFalseIfx,right,size,7);
6395             if(ifx) ifx->generated = 1;
6396             return;
6397           }
6398
6399           if(lit == 0) {
6400             int s = size;
6401
6402             if(rFalseIfx.condition) {
6403               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6404               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6405             }
6406
6407             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6408             while(size--)
6409               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6410
6411
6412             emitSKPZ;
6413             if(rFalseIfx.condition) {
6414               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6415               pic16_emitpLabel(truelbl->key);
6416             }else {
6417               rFalseIfx.condition ^= 1;
6418               genSkipCond(&rFalseIfx,right,s,7);
6419             }
6420
6421             if(ifx) ifx->generated = 1;
6422             return;
6423           }
6424
6425           if((size == 1) &&  (0 == (lp1&0xff))) {
6426             /* lower byte of signed word is zero */
6427             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6428             i = ((lp1 >> 8) & 0xff) ^0x80;
6429             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6430             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6431             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6432             rFalseIfx.condition ^= 1;
6433             genSkipc(&rFalseIfx);
6434
6435
6436             if(ifx) ifx->generated = 1;
6437             return;
6438           }
6439
6440           if(lit & (0x80 << (size*8))) {
6441             /* Lit is less than zero */
6442             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6443             //rFalseIfx.condition ^= 1;
6444             //genSkipCond(&rFalseIfx,left,size,7);
6445             //rFalseIfx.condition ^= 1;
6446             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6447             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6448
6449             if(rFalseIfx.condition)
6450               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6451             else
6452               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6453
6454
6455           } else {
6456             /* Lit is greater than or equal to zero */
6457             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6458             //rFalseIfx.condition ^= 1;
6459             //genSkipCond(&rFalseIfx,right,size,7);
6460             //rFalseIfx.condition ^= 1;
6461
6462             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6463             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6464
6465             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6466             if(rFalseIfx.condition)
6467               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6468             else
6469               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6470
6471           }
6472
6473
6474           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6475           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6476
6477           while(size--) {
6478
6479             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6480             emitSKPNZ;
6481             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6482           }
6483           rFalseIfx.condition ^= 1;
6484           //rFalseIfx.condition = 1;
6485           genSkipc(&rFalseIfx);
6486
6487           pic16_emitpLabel(truelbl->key);
6488
6489           if(ifx) ifx->generated = 1;
6490           return;
6491           // end of if (sign)
6492         } else {
6493
6494           /* compare word or long to an unsigned literal on the right.*/
6495
6496
6497           size--;
6498           if(lit < 0xff) {
6499             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6500             switch (lit) {
6501             case 0:
6502               break; /* handled above */
6503 /*
6504             case 0xff:
6505               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6506               while(size--)
6507                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6508               genSkipz2(&rFalseIfx,0);
6509               break;
6510 */
6511             default:
6512               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6513               while(--size)
6514                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6515
6516               emitSKPZ;
6517               if(rFalseIfx.condition)
6518                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6519               else
6520                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6521
6522
6523               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6524               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6525
6526               rFalseIfx.condition ^= 1;
6527               genSkipc(&rFalseIfx);
6528             }
6529
6530             pic16_emitpLabel(truelbl->key);
6531
6532             if(ifx) ifx->generated = 1;
6533             return;
6534           }
6535
6536
6537           lit++;
6538           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6539           i = (lit >> (size*8)) & 0xff;
6540
6541           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6542           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6543
6544           while(size--) {
6545             i = (lit >> (size*8)) & 0xff;
6546
6547             if(i) {
6548               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6549               emitSKPNZ;
6550               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6551             } else {
6552               /* this byte of the lit is zero, 
6553                * if it's not the last then OR in the variable */
6554               if(size)
6555                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6556             }
6557           }
6558
6559
6560           pic16_emitpLabel(lbl->key);
6561
6562           rFalseIfx.condition ^= 1;
6563
6564           genSkipc(&rFalseIfx);
6565         }
6566
6567         if(sign)
6568           pic16_emitpLabel(truelbl->key);
6569         if(ifx) ifx->generated = 1;
6570         return;
6571       }
6572     }
6573     /* Compare two variables */
6574
6575     DEBUGpic16_emitcode(";sign","%d",sign);
6576
6577     size--;
6578     if(sign) {
6579       /* Sigh. thus sucks... */
6580       if(size) {
6581         pCodeOp *pctemp;
6582         
6583         pctemp = pic16_popGetTempReg(1);
6584         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6585         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6587         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6588         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6589         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6590         pic16_popReleaseTempReg(pctemp, 1);
6591       } else {
6592         /* Signed char comparison */
6593         /* Special thanks to Nikolai Golovchenko for this snippet */
6594         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6595         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6596         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6597         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6598         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6599         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6600
6601         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6602         genSkipc(&rFalseIfx);
6603           
6604         if(ifx) ifx->generated = 1;
6605         return;
6606       }
6607
6608     } else {
6609
6610       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6611       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6612     }
6613
6614
6615     /* The rest of the bytes of a multi-byte compare */
6616     while (size) {
6617
6618       emitSKPZ;
6619       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6620       size--;
6621
6622       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6623       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6624
6625
6626     }
6627
6628     pic16_emitpLabel(lbl->key);
6629
6630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6631     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6632         (AOP_TYPE(result) == AOP_REG)) {
6633       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6634       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6635     } else {
6636       genSkipc(&rFalseIfx);
6637     }         
6638     //genSkipc(&rFalseIfx);
6639     if(ifx) ifx->generated = 1;
6640
6641     return;
6642
6643   }
6644
6645 check_carry:
6646   if ((AOP_TYPE(result) != AOP_CRY) 
6647         && AOP_SIZE(result)) {
6648     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6649
6650     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6651
6652     pic16_outBitC(result);
6653   } else {
6654     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6655     /* if the result is used in the next
6656        ifx conditional branch then generate
6657        code a little differently */
6658     if (ifx )
6659       genIfxJump (ifx,"c");
6660     else
6661       pic16_outBitC(result);
6662     /* leave the result in acc */
6663   }
6664
6665 }
6666 #endif  /* } */
6667
6668
6669 #endif  /* } */
6670
6671
6672
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpGt :- greater than comparison                             */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpGt (iCode *ic, iCode *ifx)
6677 {
6678   operand *left, *right, *result;
6679   sym_link *letype , *retype;
6680   int sign ;
6681
6682     FENTRY;
6683     
6684     left = IC_LEFT(ic);
6685     right= IC_RIGHT(ic);
6686     result = IC_RESULT(ic);
6687
6688     letype = getSpec(operandType(left));
6689     retype =getSpec(operandType(right));
6690     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6691     /* assign the amsops */
6692     pic16_aopOp (left,ic,FALSE);
6693     pic16_aopOp (right,ic,FALSE);
6694     pic16_aopOp (result,ic,TRUE);
6695
6696     genCmp(right, left, result, ifx, sign);
6697
6698     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6699     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6700     pic16_freeAsmop(result,NULL,ic,TRUE); 
6701 }
6702
6703 /*-----------------------------------------------------------------*/
6704 /* genCmpLt - less than comparisons                                */
6705 /*-----------------------------------------------------------------*/
6706 static void genCmpLt (iCode *ic, iCode *ifx)
6707 {
6708   operand *left, *right, *result;
6709   sym_link *letype , *retype;
6710   int sign ;
6711
6712     FENTRY;
6713
6714     left = IC_LEFT(ic);
6715     right= IC_RIGHT(ic);
6716     result = IC_RESULT(ic);
6717
6718     letype = getSpec(operandType(left));
6719     retype =getSpec(operandType(right));
6720     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6721
6722     /* assign the amsops */
6723     pic16_aopOp (left,ic,FALSE);
6724     pic16_aopOp (right,ic,FALSE);
6725     pic16_aopOp (result,ic,TRUE);
6726
6727     genCmp(left, right, result, ifx, sign);
6728
6729     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6730     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6731     pic16_freeAsmop(result,NULL,ic,TRUE); 
6732 }
6733
6734 #if 0
6735 // not needed ATM
6736 // FIXME reenable literal optimisation when the pic16 port is stable
6737
6738 /*-----------------------------------------------------------------*/
6739 /* genc16bit2lit - compare a 16 bit value to a literal             */
6740 /*-----------------------------------------------------------------*/
6741 static void genc16bit2lit(operand *op, int lit, int offset)
6742 {
6743   int i;
6744
6745   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6746   if( (lit&0xff) == 0) 
6747     i=1;
6748   else
6749     i=0;
6750
6751   switch( BYTEofLONG(lit,i)) { 
6752   case 0:
6753     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6754     break;
6755   case 1:
6756     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6757     break;
6758   case 0xff:
6759     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6760     break;
6761   default:
6762     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6763     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6764   }
6765
6766   i ^= 1;
6767
6768   switch( BYTEofLONG(lit,i)) { 
6769   case 0:
6770     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6771     break;
6772   case 1:
6773     emitSKPNZ;
6774     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6775     break;
6776   case 0xff:
6777     emitSKPNZ;
6778     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6779     break;
6780   default:
6781     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6782     emitSKPNZ;
6783     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6784
6785   }
6786
6787 }
6788 #endif
6789
6790 #if 0
6791 // not needed ATM
6792 /*-----------------------------------------------------------------*/
6793 /* gencjneshort - compare and jump if not equal                    */
6794 /*-----------------------------------------------------------------*/
6795 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6796 {
6797   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6798   int offset = 0;
6799   int res_offset = 0;  /* the result may be a different size then left or right */
6800   int res_size = AOP_SIZE(result);
6801   resolvedIfx rIfx;
6802   symbol *lbl, *lbl_done;
6803
6804   unsigned long lit = 0L;
6805   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6806
6807   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6808   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6809   if(result)
6810     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6811   resolveIfx(&rIfx,ifx);
6812   lbl =  newiTempLabel(NULL);
6813   lbl_done =  newiTempLabel(NULL);
6814
6815
6816   /* if the left side is a literal or 
6817      if the right is in a pointer register and left 
6818      is not */
6819   if ((AOP_TYPE(left) == AOP_LIT) || 
6820       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821     operand *t = right;
6822     right = left;
6823     left = t;
6824   }
6825   if(AOP_TYPE(right) == AOP_LIT)
6826     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6827
6828   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6829     preserve_result = 1;
6830
6831   if(result && !preserve_result)
6832     {
6833       int i;
6834       for(i = 0; i < AOP_SIZE(result); i++)
6835         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6836     }
6837
6838
6839   /* if the right side is a literal then anything goes */
6840   if (AOP_TYPE(right) == AOP_LIT &&
6841       AOP_TYPE(left) != AOP_DIR ) {
6842     switch(size) {
6843     case 2:
6844       genc16bit2lit(left, lit, 0);
6845       emitSKPZ;
6846       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6847       break;
6848     default:
6849       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6850       while (size--) {
6851         if(lit & 0xff) {
6852           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6853           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6854         } else {
6855           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6856         }
6857
6858         emitSKPZ;
6859         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6860         offset++;
6861         if(res_offset < res_size-1)
6862           res_offset++;
6863         lit >>= 8;
6864       }
6865       break;
6866     }
6867   }
6868
6869   /* if the right side is in a register or in direct space or
6870      if the left is a pointer register & right is not */    
6871   else if (AOP_TYPE(right) == AOP_REG ||
6872            AOP_TYPE(right) == AOP_DIR || 
6873            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6874            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6875     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6876     int lbl_key = lbl->key;
6877
6878     if(result) {
6879       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6880       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6881     }else {
6882       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6883       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6884               __FUNCTION__,__LINE__);
6885       return;
6886     }
6887    
6888 /*     switch(size) { */
6889 /*     case 2: */
6890 /*       genc16bit2lit(left, lit, 0); */
6891 /*       emitSKPNZ; */
6892 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6893 /*       break; */
6894 /*     default: */
6895     while (size--) {
6896       int emit_skip=1;
6897       if((AOP_TYPE(left) == AOP_DIR) && 
6898          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6899
6900         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6901         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6902
6903       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6904             
6905         switch (lit & 0xff) {
6906         case 0:
6907           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6908           break;
6909         case 1:
6910           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6911           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6912           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6913           emit_skip=0;
6914           break;
6915         case 0xff:
6916           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6917           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6918           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6919           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6920           emit_skip=0;
6921           break;
6922         default:
6923           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6924           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6925         }
6926         lit >>= 8;
6927
6928       } else {
6929         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6930       }
6931       if(emit_skip) {
6932         if(AOP_TYPE(result) == AOP_CRY) {
6933           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6934           if(rIfx.condition)
6935             emitSKPNZ;
6936           else
6937             emitSKPZ;
6938           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6939         } else {
6940           /* fix me. probably need to check result size too */
6941           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6942           if(rIfx.condition)
6943             emitSKPZ;
6944           else
6945             emitSKPNZ;
6946           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6947           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6948         }
6949         if(ifx)
6950           ifx->generated=1;
6951       }
6952       emit_skip++;
6953       offset++;
6954       if(res_offset < res_size-1)
6955         res_offset++;
6956     }
6957 /*       break; */
6958 /*     } */
6959   } else if(AOP_TYPE(right) == AOP_REG &&
6960             AOP_TYPE(left) != AOP_DIR){
6961
6962     while(size--) {
6963       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6964       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6965       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6966       if(rIfx.condition)
6967         emitSKPNZ;
6968       else
6969         emitSKPZ;
6970       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6971       offset++;
6972       if(res_offset < res_size-1)
6973         res_offset++;
6974     }
6975       
6976   }else{
6977     /* right is a pointer reg need both a & b */
6978     while(size--) {
6979       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6980       if(strcmp(l,"b"))
6981         pic16_emitcode("mov","b,%s",l);
6982       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6983       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6984       offset++;
6985     }
6986   }
6987
6988   if(result && preserve_result)
6989     {
6990       int i;
6991       for(i = 0; i < AOP_SIZE(result); i++)
6992         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6993     }
6994
6995   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6996
6997   if(result && preserve_result)
6998     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6999
7000   if(!rIfx.condition)
7001     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7002
7003   pic16_emitpLabel(lbl->key);
7004
7005   if(result && preserve_result)
7006     {
7007       int i;
7008       for(i = 0; i < AOP_SIZE(result); i++)
7009         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7010
7011       pic16_emitpLabel(lbl_done->key);
7012    }
7013
7014   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7015
7016   if(ifx)
7017     ifx->generated = 1;
7018 }
7019 #endif
7020
7021 #if 0
7022 /*-----------------------------------------------------------------*/
7023 /* gencjne - compare and jump if not equal                         */
7024 /*-----------------------------------------------------------------*/
7025 static void gencjne(operand *left, operand *right, iCode *ifx)
7026 {
7027     symbol *tlbl  = newiTempLabel(NULL);
7028
7029     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7030     gencjneshort(left, right, lbl);
7031
7032     pic16_emitcode("mov","a,%s",one);
7033     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7034     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7035     pic16_emitcode("clr","a");
7036     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7037
7038     pic16_emitpLabel(lbl->key);
7039     pic16_emitpLabel(tlbl->key);
7040
7041 }
7042 #endif
7043
7044
7045 /*-----------------------------------------------------------------*/
7046 /* is_LitOp - check if operand has to be treated as literal        */
7047 /*-----------------------------------------------------------------*/
7048 static bool is_LitOp(operand *op)
7049 {
7050   return ((AOP_TYPE(op) == AOP_LIT)
7051       || ( (AOP_TYPE(op) == AOP_PCODE)
7052           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7053               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7054 }
7055
7056 /*-----------------------------------------------------------------*/
7057 /* is_LitAOp - check if operand has to be treated as literal        */
7058 /*-----------------------------------------------------------------*/
7059 static bool is_LitAOp(asmop *aop)
7060 {
7061   return ((aop->type == AOP_LIT)
7062       || ( (aop->type == AOP_PCODE)
7063           && ( (aop->aopu.pcop->type == PO_LITERAL)
7064               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7065 }
7066
7067
7068
7069 /*-----------------------------------------------------------------*/
7070 /* genCmpEq - generates code for equal to                          */
7071 /*-----------------------------------------------------------------*/
7072 static void genCmpEq (iCode *ic, iCode *ifx)
7073 {
7074   operand *left, *right, *result;
7075   symbol *falselbl = newiTempLabel(NULL);
7076   symbol *donelbl = newiTempLabel(NULL);
7077
7078   int preserve_result = 0;
7079   int generate_result = 0;
7080   int i=0;
7081   unsigned long lit = -1;
7082
7083   FENTRY;
7084   
7085   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7086   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7087   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7088  
7089   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7090
7091   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7092     {
7093       werror(W_POSSBUG2, __FILE__, __LINE__);
7094       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7095       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7096       goto release;
7097     }
7098
7099   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7100     {
7101       operand *tmp = right ;
7102       right = left;
7103       left = tmp;
7104     }
7105
7106   if (AOP_TYPE(right) == AOP_LIT) {
7107     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7108   }
7109
7110   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7111     preserve_result = 1;
7112
7113   if(result && AOP_SIZE(result))
7114     generate_result = 1;
7115
7116   if(generate_result && !preserve_result)
7117     {
7118       for(i = 0; i < AOP_SIZE(result); i++)
7119         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7120     }
7121
7122   for(i=0; i < AOP_SIZE(left); i++)
7123     {
7124       if(AOP_TYPE(left) != AOP_ACC)
7125         {
7126           if(is_LitOp(left))
7127             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7128           else
7129             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7130         }
7131       if(is_LitOp(right)) {
7132         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7133           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7134         }
7135       } else
7136         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7137
7138       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7139     }
7140
7141   // result == true
7142
7143   if(generate_result && preserve_result)
7144     {
7145       for(i = 0; i < AOP_SIZE(result); i++)
7146         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7147     }
7148
7149   if(generate_result)
7150     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7151
7152   if(generate_result && preserve_result)
7153     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7154
7155   if(ifx && IC_TRUE(ifx))
7156     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7157
7158   if(ifx && IC_FALSE(ifx))
7159     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7160
7161   pic16_emitpLabel(falselbl->key);
7162
7163   // result == false
7164
7165   if(ifx && IC_FALSE(ifx))
7166     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7167
7168   if(generate_result && preserve_result)
7169     {
7170       for(i = 0; i < AOP_SIZE(result); i++)
7171         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7172     }
7173
7174   pic16_emitpLabel(donelbl->key);
7175
7176   if(ifx)
7177     ifx->generated = 1;
7178
7179 release:
7180   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7181   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7182   pic16_freeAsmop(result,NULL,ic,TRUE);
7183
7184 }
7185
7186
7187 #if 0
7188 // old version kept for reference
7189
7190 /*-----------------------------------------------------------------*/
7191 /* genCmpEq - generates code for equal to                          */
7192 /*-----------------------------------------------------------------*/
7193 static void genCmpEq (iCode *ic, iCode *ifx)
7194 {
7195     operand *left, *right, *result;
7196     unsigned long lit = 0L;
7197     int size,offset=0;
7198     symbol *falselbl  = newiTempLabel(NULL);
7199
7200
7201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7202
7203     if(ifx)
7204       DEBUGpic16_emitcode ("; ifx is non-null","");
7205     else
7206       DEBUGpic16_emitcode ("; ifx is null","");
7207
7208     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7209     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7210     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7211
7212     size = max(AOP_SIZE(left),AOP_SIZE(right));
7213
7214     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7215
7216     /* if literal, literal on the right or 
7217     if the right is in a pointer register and left 
7218     is not */
7219     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7220         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7221       operand *tmp = right ;
7222       right = left;
7223       left = tmp;
7224     }
7225
7226
7227     if(ifx && !AOP_SIZE(result)){
7228         symbol *tlbl;
7229         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7230         /* if they are both bit variables */
7231         if (AOP_TYPE(left) == AOP_CRY &&
7232             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7233                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7234             if(AOP_TYPE(right) == AOP_LIT){
7235                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7236                 if(lit == 0L){
7237                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7238                     pic16_emitcode("cpl","c");
7239                 } else if(lit == 1L) {
7240                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7241                 } else {
7242                     pic16_emitcode("clr","c");
7243                 }
7244                 /* AOP_TYPE(right) == AOP_CRY */
7245             } else {
7246                 symbol *lbl = newiTempLabel(NULL);
7247                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7248                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7249                 pic16_emitcode("cpl","c");
7250                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7251             }
7252             /* if true label then we jump if condition
7253             supplied is true */
7254             tlbl = newiTempLabel(NULL);
7255             if ( IC_TRUE(ifx) ) {
7256                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7257                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7258             } else {
7259                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7260                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7261             }
7262             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7263
7264                 {
7265                 /* left and right are both bit variables, result is carry */
7266                         resolvedIfx rIfx;
7267               
7268                         resolveIfx(&rIfx,ifx);
7269
7270                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7271                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7272                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7273                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7274                         genSkipz2(&rIfx,0);
7275                 }
7276         } else {
7277
7278                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7279
7280                         /* They're not both bit variables. Is the right a literal? */
7281                         if(AOP_TYPE(right) == AOP_LIT) {
7282                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7283             
7284                         switch(size) {
7285
7286                                 case 1:
7287                                         switch(lit & 0xff) {
7288                                                 case 1:
7289                                                                 if ( IC_TRUE(ifx) ) {
7290                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7291                                                                         emitSKPNZ;
7292                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7293                                                                 } else {
7294                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7295                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7296                                                                 }
7297                                                                 break;
7298                                                 case 0xff:
7299                                                                 if ( IC_TRUE(ifx) ) {
7300                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7301                                                                         emitSKPNZ;
7302                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7303                                                                 } else {
7304                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7305                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7306                                                                 }
7307                                                                 break;
7308                                                 default:
7309                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7310                                                                 if(lit)
7311                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7312                                                                 genSkip(ifx,'z');
7313                                         } // switch lit
7314
7315
7316                                         /* end of size == 1 */
7317                                         break;
7318               
7319                                 case 2:
7320                                         genc16bit2lit(left,lit,offset);
7321                                         genSkip(ifx,'z');
7322                                         break;
7323                                         /* end of size == 2 */
7324
7325                                 default:
7326                                         /* size is 4 */
7327                                         if(lit==0) {
7328                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7329                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7330                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7331                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7332                                                 genSkip(ifx,'z');
7333                                         } else {
7334                                                 /* search for patterns that can be optimized */
7335
7336                                                 genc16bit2lit(left,lit,0);
7337                                                 lit >>= 16;
7338                                                 if(lit) {
7339                                                                 if(IC_TRUE(ifx))
7340                                                                 emitSKPZ; // if hi word unequal
7341                                                                 else
7342                                                                 emitSKPNZ; // if hi word equal
7343                                                                 // fail early
7344                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7345                                                         genc16bit2lit(left,lit,2);
7346                                                         genSkip(ifx,'z');
7347                                                 } else {
7348                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7349                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7350                                                         genSkip(ifx,'z');
7351                                                 }
7352                                         }
7353                                                 pic16_emitpLabel(falselbl->key);
7354                                                 break;
7355
7356                         } // switch size
7357           
7358                         ifx->generated = 1;
7359                         goto release ;
7360             
7361
7362           } else if(AOP_TYPE(right) == AOP_CRY ) {
7363             /* we know the left is not a bit, but that the right is */
7364             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7365             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7366                       pic16_popGet(AOP(right),offset));
7367             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7368
7369             /* if the two are equal, then W will be 0 and the Z bit is set
7370              * we could test Z now, or go ahead and check the high order bytes if
7371              * the variable we're comparing is larger than a byte. */
7372
7373             while(--size)
7374               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7375
7376             if ( IC_TRUE(ifx) ) {
7377               emitSKPNZ;
7378               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7379               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7380             } else {
7381               emitSKPZ;
7382               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7383               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7384             }
7385
7386           } else {
7387             /* They're both variables that are larger than bits */
7388             int s = size;
7389
7390             tlbl = newiTempLabel(NULL);
7391
7392             while(size--) {
7393               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7394               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7395
7396               if ( IC_TRUE(ifx) ) {
7397                 if(size) {
7398                   emitSKPZ;
7399                 
7400                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7401
7402                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7403                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7404                 } else {
7405                   emitSKPNZ;
7406
7407                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7408
7409
7410                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7411                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7412                 }
7413               } else {
7414                 emitSKPZ;
7415
7416                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7417
7418                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7419                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7420               }
7421               offset++;
7422             }
7423             if(s>1 && IC_TRUE(ifx)) {
7424               pic16_emitpLabel(tlbl->key);
7425               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7426             }
7427           }
7428         }
7429         /* mark the icode as generated */
7430         ifx->generated = 1;
7431         goto release ;
7432     }
7433
7434     /* if they are both bit variables */
7435     if (AOP_TYPE(left) == AOP_CRY &&
7436         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7437         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7438         if(AOP_TYPE(right) == AOP_LIT){
7439             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7440             if(lit == 0L){
7441                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7442                 pic16_emitcode("cpl","c");
7443             } else if(lit == 1L) {
7444                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7445             } else {
7446                 pic16_emitcode("clr","c");
7447             }
7448             /* AOP_TYPE(right) == AOP_CRY */
7449         } else {
7450             symbol *lbl = newiTempLabel(NULL);
7451             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7452             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7453             pic16_emitcode("cpl","c");
7454             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7455         }
7456         /* c = 1 if egal */
7457         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7458             pic16_outBitC(result);
7459             goto release ;
7460         }
7461         if (ifx) {
7462             genIfxJump (ifx,"c");
7463             goto release ;
7464         }
7465         /* if the result is used in an arithmetic operation
7466         then put the result in place */
7467         pic16_outBitC(result);
7468     } else {
7469       
7470       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7471       gencjne(left,right,result,ifx);
7472 /*
7473       if(ifx) 
7474         gencjne(left,right,newiTempLabel(NULL));
7475       else {
7476         if(IC_TRUE(ifx)->key)
7477           gencjne(left,right,IC_TRUE(ifx)->key);
7478         else
7479           gencjne(left,right,IC_FALSE(ifx)->key);
7480         ifx->generated = 1;
7481         goto release ;
7482       }
7483       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7484         pic16_aopPut(AOP(result),"a",0);
7485         goto release ;
7486       }
7487
7488       if (ifx) {
7489         genIfxJump (ifx,"a");
7490         goto release ;
7491       }
7492 */
7493       /* if the result is used in an arithmetic operation
7494          then put the result in place */
7495 /*
7496       if (AOP_TYPE(result) != AOP_CRY) 
7497         pic16_outAcc(result);
7498 */
7499       /* leave the result in acc */
7500     }
7501
7502 release:
7503     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7504     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7505     pic16_freeAsmop(result,NULL,ic,TRUE);
7506 }
7507 #endif
7508
7509 /*-----------------------------------------------------------------*/
7510 /* ifxForOp - returns the icode containing the ifx for operand     */
7511 /*-----------------------------------------------------------------*/
7512 static iCode *ifxForOp ( operand *op, iCode *ic )
7513 {
7514   FENTRY2;
7515
7516     /* if true symbol then needs to be assigned */
7517     if (IS_TRUE_SYMOP(op))
7518         return NULL ;
7519
7520     /* if this has register type condition and
7521     the next instruction is ifx with the same operand
7522     and live to of the operand is upto the ifx only then */
7523     if (ic->next
7524         && ic->next->op == IFX
7525         && IC_COND(ic->next)->key == op->key
7526         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7527         ) {
7528                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7529           return ic->next;
7530     }
7531
7532     /*
7533     if (ic->next &&
7534         ic->next->op == IFX &&
7535         IC_COND(ic->next)->key == op->key) {
7536       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7537       return ic->next;
7538     }
7539     */
7540
7541     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7542     if (ic->next &&
7543         ic->next->op == IFX)
7544       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7545
7546     if (ic->next &&
7547         ic->next->op == IFX &&
7548         IC_COND(ic->next)->key == op->key) {
7549       DEBUGpic16_emitcode ("; "," key is okay");
7550       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7551                            OP_SYMBOL(op)->liveTo,
7552                            ic->next->seq);
7553     }
7554
7555 #if 0
7556     /* the code below is completely untested
7557      * it just allows ulong2fs.c compile -- VR */
7558          
7559     ic = ic->next;
7560     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7561                                         __FILE__, __FUNCTION__, __LINE__);
7562         
7563     /* if this has register type condition and
7564     the next instruction is ifx with the same operand
7565     and live to of the operand is upto the ifx only then */
7566     if (ic->next &&
7567         ic->next->op == IFX &&
7568         IC_COND(ic->next)->key == op->key &&
7569         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7570         return ic->next;
7571
7572     if (ic->next &&
7573         ic->next->op == IFX &&
7574         IC_COND(ic->next)->key == op->key) {
7575       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7576       return ic->next;
7577     }
7578
7579     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7580                                         __FILE__, __FUNCTION__, __LINE__);
7581
7582 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7583 #endif
7584
7585     return NULL;
7586 }
7587 /*-----------------------------------------------------------------*/
7588 /* genAndOp - for && operation                                     */
7589 /*-----------------------------------------------------------------*/
7590 static void genAndOp (iCode *ic)
7591 {
7592   operand *left,*right, *result;
7593 /*     symbol *tlbl; */
7594
7595     FENTRY;
7596
7597     /* note here that && operations that are in an
7598     if statement are taken away by backPatchLabels
7599     only those used in arthmetic operations remain */
7600     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7601     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7602     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7603
7604     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7605
7606     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7607     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7608     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7609
7610     /* if both are bit variables */
7611 /*     if (AOP_TYPE(left) == AOP_CRY && */
7612 /*         AOP_TYPE(right) == AOP_CRY ) { */
7613 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7614 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7615 /*         pic16_outBitC(result); */
7616 /*     } else { */
7617 /*         tlbl = newiTempLabel(NULL); */
7618 /*         pic16_toBoolean(left);     */
7619 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7620 /*         pic16_toBoolean(right); */
7621 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7622 /*         pic16_outBitAcc(result); */
7623 /*     } */
7624
7625     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7626     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7627     pic16_freeAsmop(result,NULL,ic,TRUE);
7628 }
7629
7630
7631 /*-----------------------------------------------------------------*/
7632 /* genOrOp - for || operation                                      */
7633 /*-----------------------------------------------------------------*/
7634 /*
7635   tsd pic port -
7636   modified this code, but it doesn't appear to ever get called
7637 */
7638
7639 static void genOrOp (iCode *ic)
7640 {
7641   operand *left,*right, *result;
7642   symbol *tlbl;
7643
7644     FENTRY;  
7645
7646   /* note here that || operations that are in an
7647     if statement are taken away by backPatchLabels
7648     only those used in arthmetic operations remain */
7649     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7650     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7651     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7652
7653     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7654
7655     /* if both are bit variables */
7656     if (AOP_TYPE(left) == AOP_CRY &&
7657         AOP_TYPE(right) == AOP_CRY ) {
7658       pic16_emitcode("clrc","");
7659       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7660                AOP(left)->aopu.aop_dir,
7661                AOP(left)->aopu.aop_dir);
7662       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7663                AOP(right)->aopu.aop_dir,
7664                AOP(right)->aopu.aop_dir);
7665       pic16_emitcode("setc","");
7666
7667     } else {
7668         tlbl = newiTempLabel(NULL);
7669         pic16_toBoolean(left);
7670         emitSKPZ;
7671         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7672         pic16_toBoolean(right);
7673         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7674
7675         pic16_outBitAcc(result);
7676     }
7677
7678     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680     pic16_freeAsmop(result,NULL,ic,TRUE);            
7681 }
7682
7683 /*-----------------------------------------------------------------*/
7684 /* isLiteralBit - test if lit == 2^n                               */
7685 /*-----------------------------------------------------------------*/
7686 static int isLiteralBit(unsigned long lit)
7687 {
7688     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7689     0x100L,0x200L,0x400L,0x800L,
7690     0x1000L,0x2000L,0x4000L,0x8000L,
7691     0x10000L,0x20000L,0x40000L,0x80000L,
7692     0x100000L,0x200000L,0x400000L,0x800000L,
7693     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7694     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7695     int idx;
7696     
7697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7698     for(idx = 0; idx < 32; idx++)
7699         if(lit == pw[idx])
7700             return idx+1;
7701     return 0;
7702 }
7703
7704 /*-----------------------------------------------------------------*/
7705 /* continueIfTrue -                                                */
7706 /*-----------------------------------------------------------------*/
7707 static void continueIfTrue (iCode *ic)
7708 {
7709   FENTRY;
7710   if(IC_TRUE(ic))
7711     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7712   ic->generated = 1;
7713 }
7714
7715 /*-----------------------------------------------------------------*/
7716 /* jmpIfTrue -                                                     */
7717 /*-----------------------------------------------------------------*/
7718 static void jumpIfTrue (iCode *ic)
7719 {
7720   FENTRY;
7721   if(!IC_TRUE(ic))
7722     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7723   ic->generated = 1;
7724 }
7725
7726 /*-----------------------------------------------------------------*/
7727 /* jmpTrueOrFalse -                                                */
7728 /*-----------------------------------------------------------------*/
7729 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7730 {
7731   // ugly but optimized by peephole
7732   FENTRY;
7733   if(IC_TRUE(ic)){
7734     symbol *nlbl = newiTempLabel(NULL);
7735       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7736       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7737       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7738       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7739   } else {
7740     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7741     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7742   }
7743   ic->generated = 1;
7744 }
7745
7746 /*-----------------------------------------------------------------*/
7747 /* genAnd  - code for and                                          */
7748 /*-----------------------------------------------------------------*/
7749 static void genAnd (iCode *ic, iCode *ifx)
7750 {
7751   operand *left, *right, *result;
7752   int size, offset=0;  
7753   unsigned long lit = 0L;
7754   int bytelit = 0;
7755   resolvedIfx rIfx;
7756
7757     FENTRY;
7758     
7759   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7760   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7761   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7762
7763   resolveIfx(&rIfx,ifx);
7764
7765   /* if left is a literal & right is not then exchange them */
7766   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7767       AOP_NEEDSACC(left)) {
7768     operand *tmp = right ;
7769     right = left;
7770     left = tmp;
7771   }
7772
7773   /* if result = right then exchange them */
7774   if(pic16_sameRegs(AOP(result),AOP(right))){
7775     operand *tmp = right ;
7776     right = left;
7777     left = tmp;
7778   }
7779
7780   /* if right is bit then exchange them */
7781   if (AOP_TYPE(right) == AOP_CRY &&
7782       AOP_TYPE(left) != AOP_CRY){
7783     operand *tmp = right ;
7784     right = left;
7785     left = tmp;
7786   }
7787   if(AOP_TYPE(right) == AOP_LIT)
7788     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7789
7790   size = AOP_SIZE(result);
7791
7792   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7793
7794   // if(bit & yy)
7795   // result = bit & yy;
7796   if (AOP_TYPE(left) == AOP_CRY){
7797     // c = bit & literal;
7798     if(AOP_TYPE(right) == AOP_LIT){
7799       if(lit & 1) {
7800         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7801           // no change
7802           goto release;
7803         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7804       } else {
7805         // bit(result) = 0;
7806         if(size && (AOP_TYPE(result) == AOP_CRY)){
7807           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7808           goto release;
7809         }
7810         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7811           jumpIfTrue(ifx);
7812           goto release;
7813         }
7814         pic16_emitcode("clr","c");
7815       }
7816     } else {
7817       if (AOP_TYPE(right) == AOP_CRY){
7818         // c = bit & bit;
7819         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7820         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7821       } else {
7822         // c = bit & val;
7823         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7824         // c = lsb
7825         pic16_emitcode("rrc","a");
7826         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7827       }
7828     }
7829     // bit = c
7830     // val = c
7831     if(size)
7832       pic16_outBitC(result);
7833     // if(bit & ...)
7834     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7835       genIfxJump(ifx, "c");           
7836     goto release ;
7837   }
7838
7839   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7840   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7841   if((AOP_TYPE(right) == AOP_LIT) &&
7842      (AOP_TYPE(result) == AOP_CRY) &&
7843      (AOP_TYPE(left) != AOP_CRY)){
7844     int posbit = isLiteralBit(lit);
7845     /* left &  2^n */
7846     if(posbit){
7847       posbit--;
7848       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7849       // bit = left & 2^n
7850       if(size)
7851         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7852       // if(left &  2^n)
7853       else{
7854         if(ifx){
7855 /*
7856           if(IC_TRUE(ifx)) {
7857             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7858             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7859           } else {
7860             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7861             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7862           }
7863 */
7864         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7865         size = AOP_SIZE(left);
7866
7867         {
7868           int bp = posbit, ofs=0;
7869           
7870             while(bp > 7) {
7871               bp -= 8;
7872               ofs++;
7873             }
7874         
7875           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7876                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7877
7878         }
7879 /*
7880           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7881                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7882 */
7883           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7884           
7885           ifx->generated = 1;
7886         }
7887         goto release;
7888       }
7889     } else {
7890       symbol *tlbl = newiTempLabel(NULL);
7891       int sizel = AOP_SIZE(left);
7892
7893       if(size)
7894         emitSETC;
7895
7896       while(sizel--) {
7897         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7898
7899           /* patch provided by Aaron Colwell */
7900           if((posbit = isLiteralBit(bytelit)) != 0) {
7901               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7902                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7903                                                 (posbit-1),0, PO_GPR_REGISTER));
7904
7905               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7906 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7907           } else {
7908               if (bytelit == 0xff) {
7909                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7910                    * a peephole could optimize it out -- VR */
7911                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7912               } else {
7913                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7914                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7915               }
7916
7917               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7918                             pic16_popGetLabel(tlbl->key));
7919           }
7920         
7921 #if 0
7922           /* old code, left here for reference -- VR 09/2004 */
7923           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924           // byte ==  2^n ?
7925           if((posbit = isLiteralBit(bytelit)) != 0)
7926             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7927           else{
7928             if(bytelit != 0x0FFL)
7929               pic16_emitcode("anl","a,%s",
7930                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7931             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7932           }
7933 #endif
7934         }
7935         offset++;
7936       }
7937       // bit = left & literal
7938       if(size) {
7939         emitCLRC;
7940         pic16_emitpLabel(tlbl->key);
7941       }
7942       // if(left & literal)
7943       else {
7944         if(ifx) {
7945           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7946           ifx->generated = 1;
7947         }
7948         pic16_emitpLabel(tlbl->key);
7949         goto release;
7950       }
7951     }
7952
7953     pic16_outBitC(result);
7954     goto release ;
7955   }
7956
7957   /* if left is same as result */
7958   if(pic16_sameRegs(AOP(result),AOP(left))){
7959     int know_W = -1;
7960     for(;size--; offset++,lit>>=8) {
7961       if(AOP_TYPE(right) == AOP_LIT){
7962         switch(lit & 0xff) {
7963         case 0x00:
7964           /*  and'ing with 0 has clears the result */
7965 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7966           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7967           break;
7968         case 0xff:
7969           /* and'ing with 0xff is a nop when the result and left are the same */
7970           break;
7971
7972         default:
7973           {
7974             int p = pic16_my_powof2( (~lit) & 0xff );
7975             if(p>=0) {
7976               /* only one bit is set in the literal, so use a bcf instruction */
7977 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7978               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7979
7980             } else {
7981               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7982               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7983               if(know_W != (lit&0xff))
7984                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7985               know_W = lit &0xff;
7986               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7987             }
7988           }    
7989         }
7990       } else {
7991         if (AOP_TYPE(left) == AOP_ACC) {
7992           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7993         } else {                    
7994           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7995           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7996
7997         }
7998       }
7999     }
8000
8001   } else {
8002     // left & result in different registers
8003     if(AOP_TYPE(result) == AOP_CRY){
8004       // result = bit
8005       // if(size), result in bit
8006       // if(!size && ifx), conditional oper: if(left & right)
8007       symbol *tlbl = newiTempLabel(NULL);
8008       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8009       if(size)
8010         pic16_emitcode("setb","c");
8011       while(sizer--){
8012         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8013         pic16_emitcode("anl","a,%s",
8014                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8015         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8016         offset++;
8017       }
8018       if(size){
8019         CLRC;
8020         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8021         pic16_outBitC(result);
8022       } else if(ifx)
8023         jmpTrueOrFalse(ifx, tlbl);
8024     } else {
8025       for(;(size--);offset++) {
8026         // normal case
8027         // result = left & right
8028         if(AOP_TYPE(right) == AOP_LIT){
8029           int t = (lit >> (offset*8)) & 0x0FFL;
8030           switch(t) { 
8031           case 0x00:
8032             pic16_emitcode("clrf","%s",
8033                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8034             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8035             break;
8036           case 0xff:
8037             pic16_emitcode("movf","%s,w",
8038                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8039             pic16_emitcode("movwf","%s",
8040                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8041             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8042             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8043             break;
8044           default:
8045             pic16_emitcode("movlw","0x%x",t);
8046             pic16_emitcode("andwf","%s,w",
8047                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8048             pic16_emitcode("movwf","%s",
8049                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8050               
8051             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8052             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8053             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8054           }
8055           continue;
8056         }
8057
8058         if (AOP_TYPE(left) == AOP_ACC) {
8059           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8060           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8061         } else {
8062           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8063           pic16_emitcode("andwf","%s,w",
8064                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8065           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8066           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8067         }
8068         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8069         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8070       }
8071     }
8072   }
8073
8074   release :
8075     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8076   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8077   pic16_freeAsmop(result,NULL,ic,TRUE);     
8078 }
8079
8080 /*-----------------------------------------------------------------*/
8081 /* genOr  - code for or                                            */
8082 /*-----------------------------------------------------------------*/
8083 static void genOr (iCode *ic, iCode *ifx)
8084 {
8085     operand *left, *right, *result;
8086     int size, offset=0;
8087     unsigned long lit = 0L;
8088
8089     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8090
8091     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8092     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8093     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8094
8095     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8096
8097     /* if left is a literal & right is not then exchange them */
8098     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8099         AOP_NEEDSACC(left)) {
8100         operand *tmp = right ;
8101         right = left;
8102         left = tmp;
8103     }
8104
8105     /* if result = right then exchange them */
8106     if(pic16_sameRegs(AOP(result),AOP(right))){
8107         operand *tmp = right ;
8108         right = left;
8109         left = tmp;
8110     }
8111
8112     /* if right is bit then exchange them */
8113     if (AOP_TYPE(right) == AOP_CRY &&
8114         AOP_TYPE(left) != AOP_CRY){
8115         operand *tmp = right ;
8116         right = left;
8117         left = tmp;
8118     }
8119
8120     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8121
8122     if(AOP_TYPE(right) == AOP_LIT)
8123         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8124
8125     size = AOP_SIZE(result);
8126
8127     // if(bit | yy)
8128     // xx = bit | yy;
8129     if (AOP_TYPE(left) == AOP_CRY){
8130         if(AOP_TYPE(right) == AOP_LIT){
8131             // c = bit & literal;
8132             if(lit){
8133                 // lit != 0 => result = 1
8134                 if(AOP_TYPE(result) == AOP_CRY){
8135                   if(size)
8136                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8137                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8138                   //     AOP(result)->aopu.aop_dir,
8139                   //     AOP(result)->aopu.aop_dir);
8140                     else if(ifx)
8141                         continueIfTrue(ifx);
8142                     goto release;
8143                 }
8144             } else {
8145                 // lit == 0 => result = left
8146                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8147                     goto release;
8148                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8149             }
8150         } else {
8151             if (AOP_TYPE(right) == AOP_CRY){
8152               if(pic16_sameRegs(AOP(result),AOP(left))){
8153                 // c = bit | bit;
8154                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8155                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8156                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8157
8158                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8159                          AOP(result)->aopu.aop_dir,
8160                          AOP(result)->aopu.aop_dir);
8161                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8162                          AOP(right)->aopu.aop_dir,
8163                          AOP(right)->aopu.aop_dir);
8164                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8165                          AOP(result)->aopu.aop_dir,
8166                          AOP(result)->aopu.aop_dir);
8167               } else {
8168                 if( AOP_TYPE(result) == AOP_ACC) {
8169                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8170                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8171                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8172                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8173
8174                 } else {
8175
8176                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8177                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8178                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8179                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8180
8181                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8182                                  AOP(result)->aopu.aop_dir,
8183                                  AOP(result)->aopu.aop_dir);
8184                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8185                                  AOP(right)->aopu.aop_dir,
8186                                  AOP(right)->aopu.aop_dir);
8187                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8188                                  AOP(left)->aopu.aop_dir,
8189                                  AOP(left)->aopu.aop_dir);
8190                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8191                                  AOP(result)->aopu.aop_dir,
8192                                  AOP(result)->aopu.aop_dir);
8193                 }
8194               }
8195             } else {
8196                 // c = bit | val;
8197                 symbol *tlbl = newiTempLabel(NULL);
8198                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8199
8200
8201                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8202                 if( AOP_TYPE(right) == AOP_ACC) {
8203                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8204                   emitSKPNZ;
8205                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8206                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8207                 }
8208
8209
8210
8211                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8212                     pic16_emitcode(";XXX setb","c");
8213                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8214                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8215                 pic16_toBoolean(right);
8216                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8217                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8218                     jmpTrueOrFalse(ifx, tlbl);
8219                     goto release;
8220                 } else {
8221                     CLRC;
8222                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8223                 }
8224             }
8225         }
8226         // bit = c
8227         // val = c
8228         if(size)
8229             pic16_outBitC(result);
8230         // if(bit | ...)
8231         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8232             genIfxJump(ifx, "c");           
8233         goto release ;
8234     }
8235
8236     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8237     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8238     if((AOP_TYPE(right) == AOP_LIT) &&
8239        (AOP_TYPE(result) == AOP_CRY) &&
8240        (AOP_TYPE(left) != AOP_CRY)){
8241         if(lit){
8242           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8243             // result = 1
8244             if(size)
8245                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8246             else 
8247                 continueIfTrue(ifx);
8248             goto release;
8249         } else {
8250           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8251             // lit = 0, result = boolean(left)
8252             if(size)
8253                 pic16_emitcode(";XXX setb","c");
8254             pic16_toBoolean(right);
8255             if(size){
8256                 symbol *tlbl = newiTempLabel(NULL);
8257                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8258                 CLRC;
8259                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8260             } else {
8261                 genIfxJump (ifx,"a");
8262                 goto release;
8263             }
8264         }
8265         pic16_outBitC(result);
8266         goto release ;
8267     }
8268
8269     /* if left is same as result */
8270     if(pic16_sameRegs(AOP(result),AOP(left))){
8271       int know_W = -1;
8272       for(;size--; offset++,lit>>=8) {
8273         if(AOP_TYPE(right) == AOP_LIT){
8274           if((lit & 0xff) == 0)
8275             /*  or'ing with 0 has no effect */
8276             continue;
8277           else {
8278             int p = pic16_my_powof2(lit & 0xff);
8279             if(p>=0) {
8280               /* only one bit is set in the literal, so use a bsf instruction */
8281               pic16_emitpcode(POC_BSF,
8282                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8283             } else {
8284               if(know_W != (lit & 0xff))
8285                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8286               know_W = lit & 0xff;
8287               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8288             }
8289                     
8290           }
8291         } else {
8292           if (AOP_TYPE(left) == AOP_ACC) {
8293             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8294             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8295           } else {                  
8296             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8297             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8298
8299             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8300             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8301
8302           }
8303         }
8304       }
8305     } else {
8306         // left & result in different registers
8307         if(AOP_TYPE(result) == AOP_CRY){
8308             // result = bit
8309             // if(size), result in bit
8310             // if(!size && ifx), conditional oper: if(left | right)
8311             symbol *tlbl = newiTempLabel(NULL);
8312             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8313             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8314
8315
8316             if(size)
8317                 pic16_emitcode(";XXX setb","c");
8318             while(sizer--){
8319                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8320                 pic16_emitcode(";XXX orl","a,%s",
8321                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8322                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8323                 offset++;
8324             }
8325             if(size){
8326                 CLRC;
8327                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8328                 pic16_outBitC(result);
8329             } else if(ifx)
8330                 jmpTrueOrFalse(ifx, tlbl);
8331         } else for(;(size--);offset++){
8332           // normal case
8333           // result = left & right
8334           if(AOP_TYPE(right) == AOP_LIT){
8335             int t = (lit >> (offset*8)) & 0x0FFL;
8336             switch(t) { 
8337             case 0x00:
8338               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8339               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8340
8341               pic16_emitcode("movf","%s,w",
8342                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8343               pic16_emitcode("movwf","%s",
8344                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8345               break;
8346             default:
8347               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8348               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8349               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8350
8351               pic16_emitcode("movlw","0x%x",t);
8352               pic16_emitcode("iorwf","%s,w",
8353                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8354               pic16_emitcode("movwf","%s",
8355                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8356               
8357             }
8358             continue;
8359           }
8360
8361           // faster than result <- left, anl result,right
8362           // and better if result is SFR
8363           if (AOP_TYPE(left) == AOP_ACC) {
8364             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8365             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8366           } else {
8367             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8368             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8369
8370             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371             pic16_emitcode("iorwf","%s,w",
8372                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8373           }
8374           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8375           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8376         }
8377     }
8378
8379 release :
8380     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8381     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8382     pic16_freeAsmop(result,NULL,ic,TRUE);     
8383 }
8384
8385 /*-----------------------------------------------------------------*/
8386 /* genXor - code for xclusive or                                   */
8387 /*-----------------------------------------------------------------*/
8388 static void genXor (iCode *ic, iCode *ifx)
8389 {
8390   operand *left, *right, *result;
8391   int size, offset=0;
8392   unsigned long lit = 0L;
8393
8394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8395
8396   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8397   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8398   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8399
8400   /* if left is a literal & right is not ||
8401      if left needs acc & right does not */
8402   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8403       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8404     operand *tmp = right ;
8405     right = left;
8406     left = tmp;
8407   }
8408
8409   /* if result = right then exchange them */
8410   if(pic16_sameRegs(AOP(result),AOP(right))){
8411     operand *tmp = right ;
8412     right = left;
8413     left = tmp;
8414   }
8415
8416   /* if right is bit then exchange them */
8417   if (AOP_TYPE(right) == AOP_CRY &&
8418       AOP_TYPE(left) != AOP_CRY){
8419     operand *tmp = right ;
8420     right = left;
8421     left = tmp;
8422   }
8423   if(AOP_TYPE(right) == AOP_LIT)
8424     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8425
8426   size = AOP_SIZE(result);
8427
8428   // if(bit ^ yy)
8429   // xx = bit ^ yy;
8430   if (AOP_TYPE(left) == AOP_CRY){
8431     if(AOP_TYPE(right) == AOP_LIT){
8432       // c = bit & literal;
8433       if(lit>>1){
8434         // lit>>1  != 0 => result = 1
8435         if(AOP_TYPE(result) == AOP_CRY){
8436           if(size)
8437             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8438             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8439           else if(ifx)
8440             continueIfTrue(ifx);
8441           goto release;
8442         }
8443         pic16_emitcode("setb","c");
8444       } else{
8445         // lit == (0 or 1)
8446         if(lit == 0){
8447           // lit == 0, result = left
8448           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8449             goto release;
8450           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8451         } else{
8452           // lit == 1, result = not(left)
8453           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8454             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8455             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8456             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8457             goto release;
8458           } else {
8459             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8460             pic16_emitcode("cpl","c");
8461           }
8462         }
8463       }
8464
8465     } else {
8466       // right != literal
8467       symbol *tlbl = newiTempLabel(NULL);
8468       if (AOP_TYPE(right) == AOP_CRY){
8469         // c = bit ^ bit;
8470         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8471       }
8472       else{
8473         int sizer = AOP_SIZE(right);
8474         // c = bit ^ val
8475         // if val>>1 != 0, result = 1
8476         pic16_emitcode("setb","c");
8477         while(sizer){
8478           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8479           if(sizer == 1)
8480             // test the msb of the lsb
8481             pic16_emitcode("anl","a,#0xfe");
8482           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8483           sizer--;
8484         }
8485         // val = (0,1)
8486         pic16_emitcode("rrc","a");
8487       }
8488       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8489       pic16_emitcode("cpl","c");
8490       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8491     }
8492     // bit = c
8493     // val = c
8494     if(size)
8495       pic16_outBitC(result);
8496     // if(bit | ...)
8497     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8498       genIfxJump(ifx, "c");           
8499     goto release ;
8500   }
8501
8502   if(pic16_sameRegs(AOP(result),AOP(left))){
8503     /* if left is same as result */
8504     for(;size--; offset++) {
8505       if(AOP_TYPE(right) == AOP_LIT){
8506         int t  = (lit >> (offset*8)) & 0x0FFL;
8507         if(t == 0x00L)
8508           continue;
8509         else
8510           if (IS_AOP_PREG(left)) {
8511             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8512             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8513             pic16_aopPut(AOP(result),"a",offset);
8514           } else {
8515             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8516             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8517             pic16_emitcode("xrl","%s,%s",
8518                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8519                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8520           }
8521       } else {
8522         if (AOP_TYPE(left) == AOP_ACC)
8523           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8524         else {
8525           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8526           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8527 /*
8528           if (IS_AOP_PREG(left)) {
8529             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8530             pic16_aopPut(AOP(result),"a",offset);
8531           } else
8532             pic16_emitcode("xrl","%s,a",
8533                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8534 */
8535         }
8536       }
8537     }
8538   } else {
8539     // left & result in different registers
8540     if(AOP_TYPE(result) == AOP_CRY){
8541       // result = bit
8542       // if(size), result in bit
8543       // if(!size && ifx), conditional oper: if(left ^ right)
8544       symbol *tlbl = newiTempLabel(NULL);
8545       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8546       if(size)
8547         pic16_emitcode("setb","c");
8548       while(sizer--){
8549         if((AOP_TYPE(right) == AOP_LIT) &&
8550            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8551           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8552         } else {
8553           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8554           pic16_emitcode("xrl","a,%s",
8555                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8556         }
8557         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8558         offset++;
8559       }
8560       if(size){
8561         CLRC;
8562         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8563         pic16_outBitC(result);
8564       } else if(ifx)
8565         jmpTrueOrFalse(ifx, tlbl);
8566     } else for(;(size--);offset++){
8567       // normal case
8568       // result = left & right
8569       if(AOP_TYPE(right) == AOP_LIT){
8570         int t = (lit >> (offset*8)) & 0x0FFL;
8571         switch(t) { 
8572         case 0x00:
8573           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8574           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8575           pic16_emitcode("movf","%s,w",
8576                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8577           pic16_emitcode("movwf","%s",
8578                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8579           break;
8580         case 0xff:
8581           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8582           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8583           pic16_emitcode("comf","%s,w",
8584                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8585           pic16_emitcode("movwf","%s",
8586                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8587           break;
8588         default:
8589           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8590           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8591           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8592           pic16_emitcode("movlw","0x%x",t);
8593           pic16_emitcode("xorwf","%s,w",
8594                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8595           pic16_emitcode("movwf","%s",
8596                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8597
8598         }
8599         continue;
8600       }
8601
8602       // faster than result <- left, anl result,right
8603       // and better if result is SFR
8604       if (AOP_TYPE(left) == AOP_ACC) {
8605         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8606         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8607       } else {
8608         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8609         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8610         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8611         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8612       }
8613       if ( AOP_TYPE(result) != AOP_ACC){
8614         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8615         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8616       }
8617     }
8618   }
8619
8620   release :
8621     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8622   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8623   pic16_freeAsmop(result,NULL,ic,TRUE);     
8624 }
8625
8626 /*-----------------------------------------------------------------*/
8627 /* genInline - write the inline code out                           */
8628 /*-----------------------------------------------------------------*/
8629 static void genInline (iCode *ic)
8630 {
8631   char *buffer, *bp, *bp1;
8632     
8633         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8634
8635         _G.inLine += (!options.asmpeep);
8636
8637         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8638         strcpy(buffer,IC_INLINE(ic));
8639
8640         while((bp1=strstr(bp, "\\n"))) {
8641           *bp1++ = '\n';
8642           *bp1++ = ' ';
8643           bp = bp1;
8644         }
8645         bp = bp1 = buffer;
8646         
8647         /* emit each line as a code */
8648         while (*bp) {
8649                 if (*bp == '\n') {
8650                         *bp++ = '\0';
8651
8652                         if(*bp1)
8653                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8654                         bp1 = bp;
8655                 } else {
8656                         if (*bp == ':') {
8657                                 bp++;
8658                                 *bp = '\0';
8659                                 bp++;
8660
8661                                 /* print label, use this special format with NULL directive
8662                                  * to denote that the argument should not be indented with tab */
8663                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8664                                 bp1 = bp;
8665                         } else
8666                                 bp++;
8667                 }
8668         }
8669
8670         if ((bp1 != bp) && *bp1)
8671                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8672
8673
8674     Safe_free(buffer);
8675
8676     _G.inLine -= (!options.asmpeep);
8677 }
8678
8679 /*-----------------------------------------------------------------*/
8680 /* genRRC - rotate right with carry                                */
8681 /*-----------------------------------------------------------------*/
8682 static void genRRC (iCode *ic)
8683 {
8684   operand *left , *result ;
8685   int size, offset = 0, same;
8686
8687   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8688
8689   /* rotate right with carry */
8690   left = IC_LEFT(ic);
8691   result=IC_RESULT(ic);
8692   pic16_aopOp (left,ic,FALSE);
8693   pic16_aopOp (result,ic,TRUE);
8694
8695   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8696
8697   same = pic16_sameRegs(AOP(result),AOP(left));
8698
8699   size = AOP_SIZE(result);    
8700
8701   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8702
8703   /* get the lsb and put it into the carry */
8704   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8705
8706   offset = 0 ;
8707
8708   while(size--) {
8709
8710     if(same) {
8711       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8712     } else {
8713       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8714       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8715     }
8716
8717     offset++;
8718   }
8719
8720   pic16_freeAsmop(left,NULL,ic,TRUE);
8721   pic16_freeAsmop(result,NULL,ic,TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genRLC - generate code for rotate left with carry               */
8726 /*-----------------------------------------------------------------*/
8727 static void genRLC (iCode *ic)
8728 {    
8729   operand *left , *result ;
8730   int size, offset = 0;
8731   int same;
8732
8733   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8734   /* rotate right with carry */
8735   left = IC_LEFT(ic);
8736   result=IC_RESULT(ic);
8737   pic16_aopOp (left,ic,FALSE);
8738   pic16_aopOp (result,ic,TRUE);
8739
8740   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8741
8742   same = pic16_sameRegs(AOP(result),AOP(left));
8743
8744   /* move it to the result */
8745   size = AOP_SIZE(result);    
8746
8747   /* get the msb and put it into the carry */
8748   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8749
8750   offset = 0 ;
8751
8752   while(size--) {
8753
8754     if(same) {
8755       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8756     } else {
8757       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8758       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8759     }
8760
8761     offset++;
8762   }
8763
8764
8765   pic16_freeAsmop(left,NULL,ic,TRUE);
8766   pic16_freeAsmop(result,NULL,ic,TRUE);
8767 }
8768
8769
8770 /* gpasm can get the highest order bit with HIGH/UPPER
8771  * so the following probably is not needed -- VR */
8772  
8773 /*-----------------------------------------------------------------*/
8774 /* genGetHbit - generates code get highest order bit               */
8775 /*-----------------------------------------------------------------*/
8776 static void genGetHbit (iCode *ic)
8777 {
8778     operand *left, *result;
8779     left = IC_LEFT(ic);
8780     result=IC_RESULT(ic);
8781     pic16_aopOp (left,ic,FALSE);
8782     pic16_aopOp (result,ic,FALSE);
8783
8784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8785     /* get the highest order byte into a */
8786     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8787     if(AOP_TYPE(result) == AOP_CRY){
8788         pic16_emitcode("rlc","a");
8789         pic16_outBitC(result);
8790     }
8791     else{
8792         pic16_emitcode("rl","a");
8793         pic16_emitcode("anl","a,#0x01");
8794         pic16_outAcc(result);
8795     }
8796
8797
8798     pic16_freeAsmop(left,NULL,ic,TRUE);
8799     pic16_freeAsmop(result,NULL,ic,TRUE);
8800 }
8801
8802 #if 0
8803 /*-----------------------------------------------------------------*/
8804 /* AccRol - rotate left accumulator by known count                 */
8805 /*-----------------------------------------------------------------*/
8806 static void AccRol (int shCount)
8807 {
8808     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809     shCount &= 0x0007;              // shCount : 0..7
8810     switch(shCount){
8811         case 0 :
8812             break;
8813         case 1 :
8814             pic16_emitcode("rl","a");
8815             break;
8816         case 2 :
8817             pic16_emitcode("rl","a");
8818             pic16_emitcode("rl","a");
8819             break;
8820         case 3 :
8821             pic16_emitcode("swap","a");
8822             pic16_emitcode("rr","a");
8823             break;
8824         case 4 :
8825             pic16_emitcode("swap","a");
8826             break;
8827         case 5 :
8828             pic16_emitcode("swap","a");
8829             pic16_emitcode("rl","a");
8830             break;
8831         case 6 :
8832             pic16_emitcode("rr","a");
8833             pic16_emitcode("rr","a");
8834             break;
8835         case 7 :
8836             pic16_emitcode("rr","a");
8837             break;
8838     }
8839 }
8840 #endif
8841
8842 /*-----------------------------------------------------------------*/
8843 /* AccLsh - left shift accumulator by known count                  */
8844 /*-----------------------------------------------------------------*/
8845 static void AccLsh (int shCount)
8846 {
8847         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8848         switch(shCount){
8849                 case 0 :
8850                         return;
8851                         break;
8852                 case 1 :
8853                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8854                         break;
8855                 case 2 :
8856                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8857                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8858                         break;
8859                 case 3 :
8860                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8861                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8862                         break;
8863                 case 4 :
8864                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8865                         break;
8866                 case 5 :
8867                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8868                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8869                         break;
8870                 case 6 :
8871                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8872                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8873                         break;
8874                 case 7 :
8875                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8876                         break;
8877         }
8878
8879         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8880 }
8881
8882 /*-----------------------------------------------------------------*/
8883 /* AccRsh - right shift accumulator by known count                 */
8884 /*-----------------------------------------------------------------*/
8885 static void AccRsh (int shCount, int andmask)
8886 {
8887         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888         switch(shCount){
8889                 case 0 :
8890                         return; break;
8891                 case 1 :
8892                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8893                         break;
8894                 case 2 :
8895                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8896                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8897                         break;
8898                 case 3 :
8899                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8900                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8901                         break;
8902                 case 4 :
8903                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8904                         break;
8905                 case 5 :
8906                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8907                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8908                         break;
8909                 case 6 :
8910                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8911                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8912                         break;
8913                 case 7 :
8914                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8915                         break;
8916         }
8917         
8918         if(andmask)
8919                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8920         else
8921                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8922 }
8923
8924 #if 0
8925 /*-----------------------------------------------------------------*/
8926 /* AccSRsh - signed right shift accumulator by known count                 */
8927 /*-----------------------------------------------------------------*/
8928 static void AccSRsh (int shCount)
8929 {
8930     symbol *tlbl ;
8931     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8932     if(shCount != 0){
8933         if(shCount == 1){
8934             pic16_emitcode("mov","c,acc.7");
8935             pic16_emitcode("rrc","a");
8936         } else if(shCount == 2){
8937             pic16_emitcode("mov","c,acc.7");
8938             pic16_emitcode("rrc","a");
8939             pic16_emitcode("mov","c,acc.7");
8940             pic16_emitcode("rrc","a");
8941         } else {
8942             tlbl = newiTempLabel(NULL);
8943             /* rotate right accumulator */
8944             AccRol(8 - shCount);
8945             /* and kill the higher order bits */
8946             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8947             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8948             pic16_emitcode("orl","a,#0x%02x",
8949                      (unsigned char)~SRMask[shCount]);
8950             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8951         }
8952     }
8953 }
8954 #endif
8955
8956 /*-----------------------------------------------------------------*/
8957 /* shiftR1Left2Result - shift right one byte from left to result   */
8958 /*-----------------------------------------------------------------*/
8959 static void shiftR1Left2ResultSigned (operand *left, int offl,
8960                                 operand *result, int offr,
8961                                 int shCount)
8962 {
8963   int same;
8964
8965   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8966
8967   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8968
8969   switch(shCount) {
8970   case 1:
8971     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8972     if(same) 
8973       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8974     else {
8975       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8976       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8977     }
8978
8979     break;
8980   case 2:
8981
8982     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8983     if(same) 
8984       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8985     else {
8986       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8987       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988     }
8989     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8990     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8991
8992     break;
8993
8994   case 3:
8995     if(same)
8996       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8997     else {
8998       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8999       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000     }
9001
9002     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9003     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9004     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9005
9006     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9007     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9008
9009     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9010     break;
9011
9012   case 4:
9013     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9014     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
9015     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9016     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
9017     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9018     break;
9019   case 5:
9020     if(same) {
9021       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
9022     } else {
9023       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
9024       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9025     }
9026     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
9027     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
9028     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9029     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
9030     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9031     break;
9032
9033   case 6:
9034     if(same) {
9035       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9036       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9037       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9038       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9039       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9040       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041     } else {
9042       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9043       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9044       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9046       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9047     }
9048     break;
9049
9050   case 7:
9051     if(same) {
9052       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9053       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9054       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9055       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9056     } else {
9057       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9058       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9059       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9060     }
9061
9062   default:
9063     break;
9064   }
9065 }
9066
9067 /*-----------------------------------------------------------------*/
9068 /* shiftR1Left2Result - shift right one byte from left to result   */
9069 /*-----------------------------------------------------------------*/
9070 static void shiftR1Left2Result (operand *left, int offl,
9071                                 operand *result, int offr,
9072                                 int shCount, int sign)
9073 {
9074   int same;
9075
9076   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9077
9078   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9079
9080   /* Copy the msb into the carry if signed. */
9081   if(sign) {
9082     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9083     return;
9084   }
9085
9086
9087
9088   switch(shCount) {
9089   case 1:
9090     emitCLRC;
9091     if(same) 
9092       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9093     else {
9094       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9095       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9096     }
9097     break;
9098   case 2:
9099     emitCLRC;
9100     if(same) {
9101       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9102     } else {
9103       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9104       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9105     }
9106     emitCLRC;
9107     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9108
9109     break;
9110   case 3:
9111     if(same)
9112       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9113     else {
9114       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9115       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9116     }
9117
9118     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9119     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9120     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9121     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9122     break;
9123       
9124   case 4:
9125     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9126     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9127     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9128     break;
9129
9130   case 5:
9131     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9132     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9133     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9134     //emitCLRC;
9135     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9136
9137     break;
9138   case 6:
9139
9140     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9141     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9142     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9143     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9144     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9145     break;
9146
9147   case 7:
9148
9149     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9150     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9151     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9152
9153     break;
9154
9155   default:
9156     break;
9157   }
9158 }
9159
9160 /*-----------------------------------------------------------------*/
9161 /* shiftL1Left2Result - shift left one byte from left to result    */
9162 /*-----------------------------------------------------------------*/
9163 static void shiftL1Left2Result (operand *left, int offl,
9164                                 operand *result, int offr, int shCount)
9165 {
9166   int same;
9167
9168   //    char *l;
9169   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9170
9171   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9172   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9173     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9174     //    MOVA(l);
9175     /* shift left accumulator */
9176     //AccLsh(shCount); // don't comment out just yet...
9177   //    pic16_aopPut(AOP(result),"a",offr);
9178
9179   switch(shCount) {
9180   case 1:
9181     /* Shift left 1 bit position */
9182     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9183     if(same) {
9184       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9185     } else {
9186       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9187       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9188     }
9189     break;
9190   case 2:
9191     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9192     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9193     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9194     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9195     break;
9196   case 3:
9197     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9198     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9199     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9200     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9201     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9202     break;
9203   case 4:
9204     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9205     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9206     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9207     break;
9208   case 5:
9209     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9210     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9211     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9212     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9213     break;
9214   case 6:
9215     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9216     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9217     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9218     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9219     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9220     break;
9221   case 7:
9222     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9223     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9224     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9225     break;
9226
9227   default:
9228     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9229   }
9230
9231 }
9232
9233 /*-----------------------------------------------------------------*/
9234 /* movLeft2Result - move byte from left to result                  */
9235 /*-----------------------------------------------------------------*/
9236 static void movLeft2Result (operand *left, int offl,
9237                             operand *result, int offr)
9238 {
9239   char *l;
9240   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9241   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9242     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9243
9244     if (*l == '@' && (IS_AOP_PREG(result))) {
9245       pic16_emitcode("mov","a,%s",l);
9246       pic16_aopPut(AOP(result),"a",offr);
9247     } else {
9248       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9249       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9250     }
9251   }
9252 }
9253
9254 /*-----------------------------------------------------------------*/
9255 /* shiftL2Left2Result - shift left two bytes from left to result   */
9256 /*-----------------------------------------------------------------*/
9257 static void shiftL2Left2Result (operand *left, int offl,
9258                                 operand *result, int offr, int shCount)
9259 {
9260   int same = pic16_sameRegs(AOP(result), AOP(left));
9261   int i;
9262
9263   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9264
9265   if (same && (offl != offr)) { // shift bytes
9266     if (offr > offl) {
9267        for(i=1;i>-1;i--) {
9268          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9269          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9270        }
9271     } else { // just treat as different later on
9272                 same = 0;
9273     }
9274   }
9275
9276   if(same) {
9277     switch(shCount) {
9278     case 0:
9279       break;
9280     case 1:
9281     case 2:
9282     case 3:
9283
9284       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9285       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9286       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9287
9288       while(--shCount) {
9289                 emitCLRC;
9290                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9291                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9292       }
9293
9294       break;
9295     case 4:
9296     case 5:
9297       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9298       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9299       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9300       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9301       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9302       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9303       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9304       if(shCount >=5) {
9305                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9306                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9307       }
9308       break;
9309     case 6:
9310       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9311       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9312       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9313       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9314       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9315       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9316       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9317       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9318       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9319       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9320       break;
9321     case 7:
9322       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9323       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9324       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9325       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9326       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9327     }
9328
9329   } else {
9330     switch(shCount) {
9331     case 0:
9332       break;
9333     case 1:
9334     case 2:
9335     case 3:
9336       /* note, use a mov/add for the shift since the mov has a
9337          chance of getting optimized out */
9338       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9339       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9340       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9341       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9342       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9343
9344       while(--shCount) {
9345                 emitCLRC;
9346                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9347                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9348       }
9349       break;
9350
9351     case 4:
9352     case 5:
9353       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9354       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9355       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9356       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9357       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9358       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9359       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9360       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9361
9362
9363       if(shCount == 5) {
9364                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9365                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9366       }
9367       break;
9368     case 6:
9369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9370       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9372       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9373
9374       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9375       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9376       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9377       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9378       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9379       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9380       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9381       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9382       break;
9383     case 7:
9384       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9385       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9386       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9387       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9388       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9389     }
9390   }
9391
9392 }
9393 /*-----------------------------------------------------------------*/
9394 /* shiftR2Left2Result - shift right two bytes from left to result  */
9395 /*-----------------------------------------------------------------*/
9396 static void shiftR2Left2Result (operand *left, int offl,
9397                                 operand *result, int offr,
9398                                 int shCount, int sign)
9399 {
9400   int same = pic16_sameRegs(AOP(result), AOP(left));
9401   int i;
9402   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9403
9404   if (same && (offl != offr)) { // shift right bytes
9405     if (offr < offl) {
9406        for(i=0;i<2;i++) {
9407          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9408          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9409        }
9410     } else { // just treat as different later on
9411                 same = 0;
9412     }
9413   }
9414
9415   switch(shCount) {
9416   case 0:
9417     break;
9418   case 1:
9419   case 2:
9420   case 3:
9421     if(sign)
9422       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9423     else
9424       emitCLRC;
9425
9426     if(same) {
9427       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9428       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9429     } else {
9430       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9431       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9432       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9433       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9434     }
9435
9436     while(--shCount) {
9437       if(sign)
9438                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9439       else
9440                 emitCLRC;
9441       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9442       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9443     }
9444     break;
9445   case 4:
9446   case 5:
9447     if(same) {
9448
9449       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9450       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9451       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9452
9453       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9454       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9455       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9456       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9457     } else {
9458       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9459       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9460       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9461
9462       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9463       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9464       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9465       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9466       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9467     }
9468
9469     if(shCount >=5) {
9470       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9471       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9472     }
9473
9474     if(sign) {
9475       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9476       pic16_emitpcode(POC_BTFSC, 
9477                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9478       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9479     }
9480
9481     break;
9482
9483   case 6:
9484     if(same) {
9485
9486       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9487       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9488
9489       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9490       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9491       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9492       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9493       if(sign) {
9494         pic16_emitpcode(POC_BTFSC, 
9495                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9496         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9497       }
9498       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9499       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9500       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9501       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9502     } else {
9503       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9504       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9505       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9506       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9507       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9508       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9509       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9510       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9511       if(sign) {
9512         pic16_emitpcode(POC_BTFSC, 
9513                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9514         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9515       }
9516       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9517       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9518
9519         
9520     }
9521
9522     break;
9523   case 7:
9524     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9525     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9526     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9527     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9528     if(sign) {
9529       emitSKPNC;
9530       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9531     } else 
9532       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9533   }
9534 }
9535
9536
9537 /*-----------------------------------------------------------------*/
9538 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9539 /*-----------------------------------------------------------------*/
9540 static void shiftLLeftOrResult (operand *left, int offl,
9541                                 operand *result, int offr, int shCount)
9542 {
9543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544
9545     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9546     /* shift left accumulator */
9547     AccLsh(shCount);
9548     /* or with result */
9549     /* back to result */
9550     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9551 }
9552
9553 /*-----------------------------------------------------------------*/
9554 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9555 /*-----------------------------------------------------------------*/
9556 static void shiftRLeftOrResult (operand *left, int offl,
9557                                 operand *result, int offr, int shCount)
9558 {
9559     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9560     
9561     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9562     /* shift right accumulator */
9563     AccRsh(shCount, 1);
9564     /* or with result */
9565     /* back to result */
9566     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9567 }
9568
9569 /*-----------------------------------------------------------------*/
9570 /* genlshOne - left shift a one byte quantity by known count       */
9571 /*-----------------------------------------------------------------*/
9572 static void genlshOne (operand *result, operand *left, int shCount)
9573 {       
9574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9575     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9576 }
9577
9578 /*-----------------------------------------------------------------*/
9579 /* genlshTwo - left shift two bytes by known amount != 0           */
9580 /*-----------------------------------------------------------------*/
9581 static void genlshTwo (operand *result,operand *left, int shCount)
9582 {
9583     int size;
9584     
9585     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9586     size = pic16_getDataSize(result);
9587
9588     /* if shCount >= 8 */
9589     if (shCount >= 8) {
9590         shCount -= 8 ;
9591
9592         if (size > 1){
9593             if (shCount)
9594                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9595             else 
9596                 movLeft2Result(left, LSB, result, MSB16);
9597         }
9598         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9599     }
9600
9601     /*  1 <= shCount <= 7 */
9602     else {  
9603         if(size == 1)
9604             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9605         else 
9606             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9607     }
9608 }
9609
9610 /*-----------------------------------------------------------------*/
9611 /* shiftLLong - shift left one long from left to result            */
9612 /* offr = LSB or MSB16                                             */
9613 /*-----------------------------------------------------------------*/
9614 static void shiftLLong (operand *left, operand *result, int offr )
9615 {
9616     int size = AOP_SIZE(result);
9617     int same = pic16_sameRegs(AOP(left),AOP(result));
9618         int i;
9619
9620     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9621
9622         if (same && (offr == MSB16)) { //shift one byte
9623                 for(i=size-1;i>=MSB16;i--) {
9624                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9625                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9626                 }
9627         } else {
9628                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9629         }
9630         
9631     if (size > LSB+offr ){
9632                 if (same) {
9633                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9634                 } else {
9635                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9636                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9637                 }
9638          }
9639
9640     if(size > MSB16+offr){
9641                 if (same) {
9642                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9643                 } else {
9644                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9645                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9646                 }
9647     }
9648
9649     if(size > MSB24+offr){
9650                 if (same) {
9651                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9652                 } else {
9653                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9654                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9655                 }
9656     }
9657
9658     if(size > MSB32+offr){
9659                 if (same) {
9660                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9661                 } else {
9662                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9663                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9664                 }
9665     }
9666     if(offr != LSB)
9667                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668
9669 }
9670
9671 /*-----------------------------------------------------------------*/
9672 /* genlshFour - shift four byte by a known amount != 0             */
9673 /*-----------------------------------------------------------------*/
9674 static void genlshFour (operand *result, operand *left, int shCount)
9675 {
9676     int size;
9677
9678     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9679     size = AOP_SIZE(result);
9680
9681     /* if shifting more that 3 bytes */
9682     if (shCount >= 24 ) {
9683         shCount -= 24;
9684         if (shCount)
9685             /* lowest order of left goes to the highest
9686             order of the destination */
9687             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9688         else
9689             movLeft2Result(left, LSB, result, MSB32);
9690
9691                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9692                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9693                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9694
9695         return;
9696     }
9697
9698     /* more than two bytes */
9699     else if ( shCount >= 16 ) {
9700         /* lower order two bytes goes to higher order two bytes */
9701         shCount -= 16;
9702         /* if some more remaining */
9703         if (shCount)
9704             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9705         else {
9706             movLeft2Result(left, MSB16, result, MSB32);
9707             movLeft2Result(left, LSB, result, MSB24);
9708         }
9709                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9710                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9711         return;
9712     }    
9713
9714     /* if more than 1 byte */
9715     else if ( shCount >= 8 ) {
9716         /* lower order three bytes goes to higher order  three bytes */
9717         shCount -= 8;
9718         if(size == 2){
9719             if(shCount)
9720                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9721             else
9722                 movLeft2Result(left, LSB, result, MSB16);
9723         }
9724         else{   /* size = 4 */
9725             if(shCount == 0){
9726                 movLeft2Result(left, MSB24, result, MSB32);
9727                 movLeft2Result(left, MSB16, result, MSB24);
9728                 movLeft2Result(left, LSB, result, MSB16);
9729                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9730             }
9731             else if(shCount == 1)
9732                 shiftLLong(left, result, MSB16);
9733             else{
9734                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9735                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9736                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9737                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9738             }
9739         }
9740     }
9741
9742     /* 1 <= shCount <= 7 */
9743     else if(shCount <= 3)
9744     { 
9745         shiftLLong(left, result, LSB);
9746         while(--shCount >= 1)
9747             shiftLLong(result, result, LSB);
9748     }
9749     /* 3 <= shCount <= 7, optimize */
9750     else{
9751         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9752         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9753         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9754     }
9755 }
9756
9757 /*-----------------------------------------------------------------*/
9758 /* genLeftShiftLiteral - left shifting by known count              */
9759 /*-----------------------------------------------------------------*/
9760 void pic16_genLeftShiftLiteral (operand *left,
9761                                  operand *right,
9762                                  operand *result,
9763                                  iCode *ic)
9764 {    
9765     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9766     int size;
9767
9768     FENTRY;
9769     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9770     pic16_freeAsmop(right,NULL,ic,TRUE);
9771
9772     pic16_aopOp(left,ic,FALSE);
9773     pic16_aopOp(result,ic,TRUE);
9774
9775     size = getSize(operandType(result));
9776
9777 #if VIEW_SIZE
9778     pic16_emitcode("; shift left ","result %d, left %d",size,
9779              AOP_SIZE(left));
9780 #endif
9781
9782     /* I suppose that the left size >= result size */
9783     if(shCount == 0){
9784         while(size--){
9785             movLeft2Result(left, size, result, size);
9786         }
9787     }
9788
9789     else if(shCount >= (size * 8))
9790         while(size--)
9791             pic16_aopPut(AOP(result),zero,size);
9792     else{
9793         switch (size) {
9794             case 1:
9795                 genlshOne (result,left,shCount);
9796                 break;
9797
9798             case 2:
9799             case 3:
9800                 genlshTwo (result,left,shCount);
9801                 break;
9802
9803             case 4:
9804                 genlshFour (result,left,shCount);
9805                 break;
9806         }
9807     }
9808     pic16_freeAsmop(left,NULL,ic,TRUE);
9809     pic16_freeAsmop(result,NULL,ic,TRUE);
9810 }
9811
9812 /*-----------------------------------------------------------------*
9813  * genMultiAsm - repeat assembly instruction for size of register.
9814  * if endian == 1, then the high byte (i.e base address + size of 
9815  * register) is used first else the low byte is used first;
9816  *-----------------------------------------------------------------*/
9817 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9818 {
9819
9820   int offset = 0;
9821
9822   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9823
9824   if(!reg)
9825     return;
9826
9827   if(!endian) {
9828     endian = 1;
9829   } else {
9830     endian = -1;
9831     offset = size-1;
9832   }
9833
9834   while(size--) {
9835     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9836     offset += endian;
9837   }
9838
9839 }
9840
9841 #if !(USE_GENERIC_SIGNED_SHIFT)
9842 /*-----------------------------------------------------------------*/
9843 /* genLeftShift - generates code for left shifting                 */
9844 /*-----------------------------------------------------------------*/
9845 static void genLeftShift (iCode *ic)
9846 {
9847   operand *left,*right, *result;
9848   int size, offset;
9849 //  char *l;
9850   symbol *tlbl , *tlbl1;
9851   pCodeOp *pctemp;
9852
9853   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9854
9855   right = IC_RIGHT(ic);
9856   left  = IC_LEFT(ic);
9857   result = IC_RESULT(ic);
9858
9859   pic16_aopOp(right,ic,FALSE);
9860
9861   /* if the shift count is known then do it 
9862      as efficiently as possible */
9863   if (AOP_TYPE(right) == AOP_LIT) {
9864     pic16_genLeftShiftLiteral (left,right,result,ic);
9865     return ;
9866   }
9867
9868   /* shift count is unknown then we have to form
9869    * a loop. Get the loop count in WREG : Note: we take
9870    * only the lower order byte since shifting
9871    * more than 32 bits make no sense anyway, ( the
9872    * largest size of an object can be only 32 bits ) */
9873   
9874   pic16_aopOp(left,ic,FALSE);
9875   pic16_aopOp(result,ic,FALSE);
9876
9877   /* now move the left to the result if they are not the
9878    * same, and if size > 1,
9879    * and if right is not same to result (!!!) -- VR */
9880   if (!pic16_sameRegs(AOP(left),AOP(result))
9881       && (AOP_SIZE(result) > 1)) {
9882
9883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9884
9885     size = AOP_SIZE(result);
9886     offset=0;
9887     while (size--) {
9888
9889 #if 0
9890       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9891       if (*l == '@' && (IS_AOP_PREG(result))) {
9892
9893           pic16_emitcode("mov","a,%s",l);
9894           pic16_aopPut(AOP(result),"a",offset);
9895       } else
9896 #endif
9897       {
9898         /* we don't know if left is a literal or a register, take care -- VR */
9899         mov2f(AOP(result), AOP(left), offset);
9900       }
9901       offset++;
9902     }
9903   }
9904
9905   size = AOP_SIZE(result);
9906
9907   /* if it is only one byte then */
9908   if (size == 1) {
9909     if(optimized_for_speed) {
9910       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9911       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9912       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9913       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9914       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9915       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9916       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9917       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9918       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9919       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9920       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9921       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9922     } else {
9923
9924       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9925
9926       tlbl = newiTempLabel(NULL);
9927
9928 #if 1
9929       /* this is already done, why change it? */
9930       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9931                 mov2f(AOP(result), AOP(left), 0);
9932       }
9933 #endif
9934
9935       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9936       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9937       pic16_emitpLabel(tlbl->key);
9938       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9939       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9940       emitSKPC;
9941       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9942     }
9943     goto release ;
9944   }
9945     
9946   if (pic16_sameRegs(AOP(left),AOP(result))) {
9947
9948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9949     
9950     tlbl = newiTempLabel(NULL);
9951     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9952     genMultiAsm(POC_RRCF, result, size,1);
9953     pic16_emitpLabel(tlbl->key);
9954     genMultiAsm(POC_RLCF, result, size,0);
9955     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9956     emitSKPC;
9957     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9958     goto release;
9959   }
9960
9961   //tlbl = newiTempLabel(NULL);
9962   //offset = 0 ;   
9963   //tlbl1 = newiTempLabel(NULL);
9964
9965   //reAdjustPreg(AOP(result));    
9966     
9967   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9968   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9969   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9970   //MOVA(l);
9971   //pic16_emitcode("add","a,acc");         
9972   //pic16_aopPut(AOP(result),"a",offset++);
9973   //while (--size) {
9974   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9975   //  MOVA(l);
9976   //  pic16_emitcode("rlc","a");         
9977   //  pic16_aopPut(AOP(result),"a",offset++);
9978   //}
9979   //reAdjustPreg(AOP(result));
9980
9981   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9982   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9983
9984
9985   tlbl = newiTempLabel(NULL);
9986   tlbl1= newiTempLabel(NULL);
9987
9988   size = AOP_SIZE(result);
9989   offset = 1;
9990
9991   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9992
9993   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9994
9995   /* offset should be 0, 1 or 3 */
9996   
9997   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9998   emitSKPNZ;
9999   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10000
10001   pic16_emitpcode(POC_MOVWF, pctemp);
10002
10003
10004   pic16_emitpLabel(tlbl->key);
10005
10006   emitCLRC;
10007   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10008   while(--size)
10009     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10010
10011   pic16_emitpcode(POC_DECFSZ,  pctemp);
10012   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10013   pic16_emitpLabel(tlbl1->key);
10014
10015   pic16_popReleaseTempReg(pctemp,1);
10016
10017
10018  release:
10019   pic16_freeAsmop (right,NULL,ic,TRUE);
10020   pic16_freeAsmop(left,NULL,ic,TRUE);
10021   pic16_freeAsmop(result,NULL,ic,TRUE);
10022 }
10023 #endif
10024
10025
10026 #if 0
10027 #error old code (left here for reference)
10028 /*-----------------------------------------------------------------*/
10029 /* genLeftShift - generates code for left shifting                 */
10030 /*-----------------------------------------------------------------*/
10031 static void genLeftShift (iCode *ic)
10032 {
10033   operand *left,*right, *result;
10034   int size, offset;
10035   char *l;
10036   symbol *tlbl , *tlbl1;
10037   pCodeOp *pctemp;
10038
10039   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10040
10041   right = IC_RIGHT(ic);
10042   left  = IC_LEFT(ic);
10043   result = IC_RESULT(ic);
10044
10045   pic16_aopOp(right,ic,FALSE);
10046
10047   /* if the shift count is known then do it 
10048      as efficiently as possible */
10049   if (AOP_TYPE(right) == AOP_LIT) {
10050     pic16_genLeftShiftLiteral (left,right,result,ic);
10051     return ;
10052   }
10053
10054   /* shift count is unknown then we have to form 
10055      a loop get the loop count in B : Note: we take
10056      only the lower order byte since shifting
10057      more that 32 bits make no sense anyway, ( the
10058      largest size of an object can be only 32 bits ) */  
10059
10060     
10061   pic16_aopOp(left,ic,FALSE);
10062   pic16_aopOp(result,ic,FALSE);
10063
10064   /* now move the left to the result if they are not the
10065      same */
10066   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10067       AOP_SIZE(result) > 1) {
10068
10069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10070
10071     size = AOP_SIZE(result);
10072     offset=0;
10073     while (size--) {
10074       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10075       if (*l == '@' && (IS_AOP_PREG(result))) {
10076
10077         pic16_emitcode("mov","a,%s",l);
10078         pic16_aopPut(AOP(result),"a",offset);
10079       } else {
10080
10081         /* we don't know if left is a literal or a register, take care -- VR */
10082         mov2f(AOP(result), AOP(left), offset);
10083       }
10084       offset++;
10085     }
10086   }
10087
10088   size = AOP_SIZE(result);
10089
10090   /* if it is only one byte then */
10091   if (size == 1) {
10092     if(optimized_for_speed) {
10093       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10094       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10095       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10096       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10097       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10098       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10099       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10100       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10101       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10102       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10103       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10104       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10105     } else {
10106
10107       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10108
10109       tlbl = newiTempLabel(NULL);
10110       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10111                 mov2f(AOP(result), AOP(left), 0);
10112                 
10113 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10114 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10115       }
10116
10117       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10118       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10119       pic16_emitpLabel(tlbl->key);
10120       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10121       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10122       emitSKPC;
10123       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10124     }
10125     goto release ;
10126   }
10127     
10128   if (pic16_sameRegs(AOP(left),AOP(result))) {
10129
10130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10131     
10132     tlbl = newiTempLabel(NULL);
10133     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10134     genMultiAsm(POC_RRCF, result, size,1);
10135     pic16_emitpLabel(tlbl->key);
10136     genMultiAsm(POC_RLCF, result, size,0);
10137     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10138     emitSKPC;
10139     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10140     goto release;
10141   }
10142
10143   //tlbl = newiTempLabel(NULL);
10144   //offset = 0 ;   
10145   //tlbl1 = newiTempLabel(NULL);
10146
10147   //reAdjustPreg(AOP(result));    
10148     
10149   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10150   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10151   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10152   //MOVA(l);
10153   //pic16_emitcode("add","a,acc");         
10154   //pic16_aopPut(AOP(result),"a",offset++);
10155   //while (--size) {
10156   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10157   //  MOVA(l);
10158   //  pic16_emitcode("rlc","a");         
10159   //  pic16_aopPut(AOP(result),"a",offset++);
10160   //}
10161   //reAdjustPreg(AOP(result));
10162
10163   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10164   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10165
10166
10167   tlbl = newiTempLabel(NULL);
10168   tlbl1= newiTempLabel(NULL);
10169
10170   size = AOP_SIZE(result);
10171   offset = 1;
10172
10173   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10174
10175   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10176
10177   /* offset should be 0, 1 or 3 */
10178   
10179   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10180   emitSKPNZ;
10181   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10182
10183   pic16_emitpcode(POC_MOVWF, pctemp);
10184
10185
10186   pic16_emitpLabel(tlbl->key);
10187
10188   emitCLRC;
10189   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10190   while(--size)
10191     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10192
10193   pic16_emitpcode(POC_DECFSZ,  pctemp);
10194   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10195   pic16_emitpLabel(tlbl1->key);
10196
10197   pic16_popReleaseTempReg(pctemp,1);
10198
10199
10200  release:
10201   pic16_freeAsmop (right,NULL,ic,TRUE);
10202   pic16_freeAsmop(left,NULL,ic,TRUE);
10203   pic16_freeAsmop(result,NULL,ic,TRUE);
10204 }
10205 #endif
10206
10207 /*-----------------------------------------------------------------*/
10208 /* genrshOne - right shift a one byte quantity by known count      */
10209 /*-----------------------------------------------------------------*/
10210 static void genrshOne (operand *result, operand *left,
10211                        int shCount, int sign)
10212 {
10213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10214     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10215 }
10216
10217 /*-----------------------------------------------------------------*/
10218 /* genrshTwo - right shift two bytes by known amount != 0          */
10219 /*-----------------------------------------------------------------*/
10220 static void genrshTwo (operand *result,operand *left,
10221                        int shCount, int sign)
10222 {
10223   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10224   /* if shCount >= 8 */
10225   if (shCount >= 8) {
10226     shCount -= 8 ;
10227     if (shCount)
10228       shiftR1Left2Result(left, MSB16, result, LSB,
10229                          shCount, sign);
10230     else
10231       movLeft2Result(left, MSB16, result, LSB);
10232
10233     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10234
10235     if(sign) {
10236       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10237       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10238     }
10239   }
10240
10241   /*  1 <= shCount <= 7 */
10242   else
10243     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10244 }
10245
10246 /*-----------------------------------------------------------------*/
10247 /* shiftRLong - shift right one long from left to result           */
10248 /* offl = LSB or MSB16                                             */
10249 /*-----------------------------------------------------------------*/
10250 static void shiftRLong (operand *left, int offl,
10251                         operand *result, int sign)
10252 {
10253     int size = AOP_SIZE(result);
10254     int same = pic16_sameRegs(AOP(left),AOP(result));
10255     int i;
10256     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10257
10258         if (same && (offl == MSB16)) { //shift one byte right
10259                 for(i=MSB16;i<size;i++) {
10260                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10261                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10262                 }
10263         }
10264
10265     if(sign)
10266                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10267         else
10268                 emitCLRC;
10269
10270         if (same) {
10271                 if (offl == LSB)
10272                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10273         } else {
10274         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10275         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10276         }
10277
10278     if(offl == MSB16) {
10279         /* add sign of "a" */
10280         pic16_addSign(result, MSB32, sign);
10281         }
10282
10283         if (same) {
10284         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10285         } else {
10286         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10287         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10288         }
10289         
10290         if (same) {
10291         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10292         } else {
10293         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10294         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10295         }
10296
10297         if (same) {
10298         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10299         } else {
10300         if(offl == LSB){
10301                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10302                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10303         }
10304         }
10305 }
10306
10307 /*-----------------------------------------------------------------*/
10308 /* genrshFour - shift four byte by a known amount != 0             */
10309 /*-----------------------------------------------------------------*/
10310 static void genrshFour (operand *result, operand *left,
10311                         int shCount, int sign)
10312 {
10313   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10314   /* if shifting more that 3 bytes */
10315   if(shCount >= 24 ) {
10316     shCount -= 24;
10317     if(shCount)
10318       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10319     else
10320       movLeft2Result(left, MSB32, result, LSB);
10321
10322     pic16_addSign(result, MSB16, sign);
10323   }
10324   else if(shCount >= 16){
10325     shCount -= 16;
10326     if(shCount)
10327       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10328     else{
10329       movLeft2Result(left, MSB24, result, LSB);
10330       movLeft2Result(left, MSB32, result, MSB16);
10331     }
10332     pic16_addSign(result, MSB24, sign);
10333   }
10334   else if(shCount >= 8){
10335     shCount -= 8;
10336     if(shCount == 1)
10337       shiftRLong(left, MSB16, result, sign);
10338     else if(shCount == 0){
10339       movLeft2Result(left, MSB16, result, LSB);
10340       movLeft2Result(left, MSB24, result, MSB16);
10341       movLeft2Result(left, MSB32, result, MSB24);
10342       pic16_addSign(result, MSB32, sign);
10343     }
10344     else{ //shcount >= 2
10345       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10346       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10347       /* the last shift is signed */
10348       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10349       pic16_addSign(result, MSB32, sign);
10350     }
10351   }
10352   else{   /* 1 <= shCount <= 7 */
10353     if(shCount <= 2){
10354       shiftRLong(left, LSB, result, sign);
10355       if(shCount == 2)
10356         shiftRLong(result, LSB, result, sign);
10357     }
10358     else{
10359       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10360       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10361       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10362     }
10363   }
10364 }
10365
10366 /*-----------------------------------------------------------------*/
10367 /* genRightShiftLiteral - right shifting by known count            */
10368 /*-----------------------------------------------------------------*/
10369 static void genRightShiftLiteral (operand *left,
10370                                   operand *right,
10371                                   operand *result,
10372                                   iCode *ic,
10373                                   int sign)
10374 {    
10375   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10376   int lsize,res_size;
10377
10378   pic16_freeAsmop(right,NULL,ic,TRUE);
10379
10380   pic16_aopOp(left,ic,FALSE);
10381   pic16_aopOp(result,ic,TRUE);
10382
10383   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10384
10385 #if VIEW_SIZE
10386   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10387                  AOP_SIZE(left));
10388 #endif
10389
10390   lsize = pic16_getDataSize(left);
10391   res_size = pic16_getDataSize(result);
10392   /* test the LEFT size !!! */
10393
10394   /* I suppose that the left size >= result size */
10395   if(shCount == 0){
10396     assert (res_size <= lsize);
10397     while (res_size--) {
10398       mov2f (AOP(result), AOP(left), res_size);
10399     } // for
10400   }
10401
10402   else if(shCount >= (lsize * 8)){
10403
10404     if(res_size == 1) {
10405       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10406       if(sign) {
10407         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10408         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10409       }
10410     } else {
10411
10412       if(sign) {
10413         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10414         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10415         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10416         while(res_size--)
10417           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10418
10419       } else {
10420
10421         while(res_size--)
10422           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10423       }
10424     }
10425   } else {
10426
10427     switch (res_size) {
10428     case 1:
10429       genrshOne (result,left,shCount,sign);
10430       break;
10431
10432     case 2:
10433       genrshTwo (result,left,shCount,sign);
10434       break;
10435
10436     case 4:
10437       genrshFour (result,left,shCount,sign);
10438       break;
10439     default :
10440       break;
10441     }
10442
10443   }
10444
10445   pic16_freeAsmop(left,NULL,ic,TRUE);
10446   pic16_freeAsmop(result,NULL,ic,TRUE);
10447 }
10448
10449 #if !(USE_GENERIC_SIGNED_SHIFT)
10450 /*-----------------------------------------------------------------*/
10451 /* genSignedRightShift - right shift of signed number              */
10452 /*-----------------------------------------------------------------*/
10453 static void genSignedRightShift (iCode *ic)
10454 {
10455   operand *right, *left, *result;
10456   int size, offset;
10457   //  char *l;
10458   symbol *tlbl, *tlbl1 ;
10459   pCodeOp *pctemp;
10460
10461   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10462
10463   /* we do it the hard way put the shift count in b
10464      and loop thru preserving the sign */
10465   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10466
10467   right = IC_RIGHT(ic);
10468   left  = IC_LEFT(ic);
10469   result = IC_RESULT(ic);
10470
10471   pic16_aopOp(right,ic,FALSE);  
10472   pic16_aopOp(left,ic,FALSE);
10473   pic16_aopOp(result,ic,FALSE);
10474
10475
10476   if ( AOP_TYPE(right) == AOP_LIT) {
10477     genRightShiftLiteral (left,right,result,ic,1);
10478     return ;
10479   }
10480   /* shift count is unknown then we have to form 
10481      a loop get the loop count in B : Note: we take
10482      only the lower order byte since shifting
10483      more that 32 bits make no sense anyway, ( the
10484      largest size of an object can be only 32 bits ) */  
10485
10486   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10487   //pic16_emitcode("inc","b");
10488   //pic16_freeAsmop (right,NULL,ic,TRUE);
10489   //pic16_aopOp(left,ic,FALSE);
10490   //pic16_aopOp(result,ic,FALSE);
10491
10492   /* now move the left to the result if they are not the
10493      same */
10494   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10495       AOP_SIZE(result) > 1) {
10496
10497     size = AOP_SIZE(result);
10498     offset=0;
10499     while (size--) { 
10500       /*
10501         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10502         if (*l == '@' && IS_AOP_PREG(result)) {
10503
10504         pic16_emitcode("mov","a,%s",l);
10505         pic16_aopPut(AOP(result),"a",offset);
10506         } else
10507         pic16_aopPut(AOP(result),l,offset);
10508       */
10509       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10510       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10511
10512       offset++;
10513     }
10514   }
10515
10516   /* mov the highest order bit to OVR */    
10517   tlbl = newiTempLabel(NULL);
10518   tlbl1= newiTempLabel(NULL);
10519
10520   size = AOP_SIZE(result);
10521   offset = size - 1;
10522
10523   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10524
10525   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10526
10527   /* offset should be 0, 1 or 3 */
10528   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10529   emitSKPNZ;
10530   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10531
10532   pic16_emitpcode(POC_MOVWF, pctemp);
10533
10534
10535   pic16_emitpLabel(tlbl->key);
10536
10537   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10538   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10539
10540   while(--size) {
10541     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10542   }
10543
10544   pic16_emitpcode(POC_DECFSZ,  pctemp);
10545   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10546   pic16_emitpLabel(tlbl1->key);
10547
10548   pic16_popReleaseTempReg(pctemp,1);
10549 #if 0
10550   size = AOP_SIZE(result);
10551   offset = size - 1;
10552   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10553   pic16_emitcode("rlc","a");
10554   pic16_emitcode("mov","ov,c");
10555   /* if it is only one byte then */
10556   if (size == 1) {
10557     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10558     MOVA(l);
10559     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10560     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10561     pic16_emitcode("mov","c,ov");
10562     pic16_emitcode("rrc","a");
10563     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10564     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10565     pic16_aopPut(AOP(result),"a",0);
10566     goto release ;
10567   }
10568
10569   reAdjustPreg(AOP(result));
10570   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10571   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10572   pic16_emitcode("mov","c,ov");
10573   while (size--) {
10574     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10575     MOVA(l);
10576     pic16_emitcode("rrc","a");         
10577     pic16_aopPut(AOP(result),"a",offset--);
10578   }
10579   reAdjustPreg(AOP(result));
10580   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10581   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10582
10583  release:
10584 #endif
10585
10586   pic16_freeAsmop(left,NULL,ic,TRUE);
10587   pic16_freeAsmop(result,NULL,ic,TRUE);
10588   pic16_freeAsmop(right,NULL,ic,TRUE);
10589 }
10590 #endif
10591
10592 #if !(USE_GENERIC_SIGNED_SHIFT)
10593 #warning This implementation of genRightShift() is incomplete!
10594 /*-----------------------------------------------------------------*/
10595 /* genRightShift - generate code for right shifting                */
10596 /*-----------------------------------------------------------------*/
10597 static void genRightShift (iCode *ic)
10598 {
10599     operand *right, *left, *result;
10600     sym_link *letype ;
10601     int size, offset;
10602     char *l;
10603     symbol *tlbl, *tlbl1 ;
10604
10605     /* if signed then we do it the hard way preserve the
10606     sign bit moving it inwards */
10607     letype = getSpec(operandType(IC_LEFT(ic)));
10608     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10609
10610     if (!SPEC_USIGN(letype)) {
10611         genSignedRightShift (ic);
10612         return ;
10613     }
10614
10615     /* signed & unsigned types are treated the same : i.e. the
10616     signed is NOT propagated inwards : quoting from the
10617     ANSI - standard : "for E1 >> E2, is equivalent to division
10618     by 2**E2 if unsigned or if it has a non-negative value,
10619     otherwise the result is implementation defined ", MY definition
10620     is that the sign does not get propagated */
10621
10622     right = IC_RIGHT(ic);
10623     left  = IC_LEFT(ic);
10624     result = IC_RESULT(ic);
10625
10626     pic16_aopOp(right,ic,FALSE);
10627
10628     /* if the shift count is known then do it 
10629     as efficiently as possible */
10630     if (AOP_TYPE(right) == AOP_LIT) {
10631         genRightShiftLiteral (left,right,result,ic, 0);
10632         return ;
10633     }
10634
10635     /* shift count is unknown then we have to form 
10636     a loop get the loop count in B : Note: we take
10637     only the lower order byte since shifting
10638     more that 32 bits make no sense anyway, ( the
10639     largest size of an object can be only 32 bits ) */  
10640
10641     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10642     pic16_emitcode("inc","b");
10643     pic16_aopOp(left,ic,FALSE);
10644     pic16_aopOp(result,ic,FALSE);
10645
10646     /* now move the left to the result if they are not the
10647     same */
10648     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10649         AOP_SIZE(result) > 1) {
10650
10651         size = AOP_SIZE(result);
10652         offset=0;
10653         while (size--) {
10654             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10655             if (*l == '@' && IS_AOP_PREG(result)) {
10656
10657                 pic16_emitcode("mov","a,%s",l);
10658                 pic16_aopPut(AOP(result),"a",offset);
10659             } else
10660                 pic16_aopPut(AOP(result),l,offset);
10661             offset++;
10662         }
10663     }
10664
10665     tlbl = newiTempLabel(NULL);
10666     tlbl1= newiTempLabel(NULL);
10667     size = AOP_SIZE(result);
10668     offset = size - 1;
10669
10670     /* if it is only one byte then */
10671     if (size == 1) {
10672
10673       tlbl = newiTempLabel(NULL);
10674       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10675         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10676         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10677       }
10678
10679       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10680       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10681       pic16_emitpLabel(tlbl->key);
10682       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10683       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10684       emitSKPC;
10685       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10686
10687       goto release ;
10688     }
10689
10690     reAdjustPreg(AOP(result));
10691     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10692     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10693     CLRC;
10694     while (size--) {
10695         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10696         MOVA(l);
10697         pic16_emitcode("rrc","a");         
10698         pic16_aopPut(AOP(result),"a",offset--);
10699     }
10700     reAdjustPreg(AOP(result));
10701
10702     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10703     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10704
10705 release:
10706     pic16_freeAsmop(left,NULL,ic,TRUE);
10707     pic16_freeAsmop (right,NULL,ic,TRUE);
10708     pic16_freeAsmop(result,NULL,ic,TRUE);
10709 }
10710 #endif
10711
10712 #if (USE_GENERIC_SIGNED_SHIFT)
10713 /*-----------------------------------------------------------------*/
10714 /* genGenericShift - generates code for left or right shifting     */
10715 /*-----------------------------------------------------------------*/
10716 static void genGenericShift (iCode *ic, int isShiftLeft) {
10717   operand *left,*right, *result;
10718   int offset;
10719   int sign, signedCount;
10720   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10721   PIC_OPCODE pos_shift, neg_shift;
10722
10723   FENTRY;
10724
10725   right = IC_RIGHT(ic);
10726   left  = IC_LEFT(ic);
10727   result = IC_RESULT(ic);
10728
10729   pic16_aopOp(right,ic,FALSE);
10730   pic16_aopOp(left,ic,FALSE);
10731   pic16_aopOp(result,ic,TRUE);
10732
10733   sign = !SPEC_USIGN(operandType (left));
10734   signedCount = !SPEC_USIGN(operandType (right));
10735
10736   /* if the shift count is known then do it 
10737      as efficiently as possible */
10738   if (AOP_TYPE(right) == AOP_LIT) {
10739     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10740     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10741     // we should modify right->aopu.aop_lit here!
10742     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10743     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10744     if (isShiftLeft)
10745       pic16_genLeftShiftLiteral (left,right,result,ic);
10746     else
10747       genRightShiftLiteral (left,right,result,ic, sign);
10748
10749     goto release;
10750   } // if (right is literal)
10751
10752   /* shift count is unknown then we have to form a loop.
10753    * Note: we take only the lower order byte since shifting
10754    * more than 32 bits make no sense anyway, ( the
10755    * largest size of an object can be only 32 bits )
10756    * Note: we perform arithmetic shifts if the left operand is
10757    * signed and we do an (effective) right shift, i. e. we
10758    * shift in the sign bit from the left. */
10759    
10760   label_complete = newiTempLabel ( NULL );
10761   label_loop_pos = newiTempLabel ( NULL );
10762   label_loop_neg = NULL;
10763   label_negative = NULL;
10764   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10765   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10766
10767   if (signedCount) {
10768     // additional labels needed
10769     label_loop_neg = newiTempLabel ( NULL );
10770     label_negative = newiTempLabel ( NULL );
10771   } // if
10772
10773   // copy source to result -- this will effectively truncate the left operand to the size of result!
10774   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10775   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10776   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10777     mov2f (AOP(result),AOP(left), offset);
10778   } // for
10779
10780   // if result is longer than left, fill with zeros (or sign)
10781   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10782     if (sign && AOP_SIZE(left) > 0) {
10783       // shift signed operand -- fill with sign
10784       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10785       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10786       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10787       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10788         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10789       } // for
10790     } else {
10791       // shift unsigned operand -- fill result with zeros
10792       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10793         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10794       } // for
10795     }
10796   } // if (size mismatch)
10797
10798   pic16_mov2w (AOP(right), 0);
10799   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10800   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10801   
10802 #if 0
10803   // perform a shift by one (shift count is positive)
10804   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10805   // 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])
10806   pic16_emitpLabel (label_loop_pos->key);
10807   emitCLRC;
10808   if (sign && (pos_shift == POC_RRCF)) {
10809     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10810     emitSETC;
10811   } // if
10812   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10813   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10814   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10815 #else
10816   // perform a shift by one (shift count is positive)
10817   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10818   // 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])
10819   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10820   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10821   emitCLRC;
10822   pic16_emitpLabel (label_loop_pos->key);
10823   if (sign && (pos_shift == POC_RRCF)) {
10824     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10825     emitSETC;
10826   } // if
10827   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10828   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10829   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10830   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10831 #endif
10832
10833   if (signedCount) {
10834     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10835
10836     pic16_emitpLabel (label_negative->key);
10837     // perform a shift by -1 (shift count is negative)
10838     // 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)
10839     emitCLRC;
10840     pic16_emitpLabel (label_loop_neg->key);
10841     if (sign && (neg_shift == POC_RRCF)) {
10842       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10843       emitSETC;
10844     } // if
10845     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10846     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10847     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10848     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10849   } // if (signedCount)
10850
10851   pic16_emitpLabel (label_complete->key);
10852
10853 release:
10854   pic16_freeAsmop (right,NULL,ic,TRUE);
10855   pic16_freeAsmop(left,NULL,ic,TRUE);
10856   pic16_freeAsmop(result,NULL,ic,TRUE);
10857 }
10858
10859 static void genLeftShift (iCode *ic) {
10860   genGenericShift (ic, 1);
10861 }
10862
10863 static void genRightShift (iCode *ic) {
10864   genGenericShift (ic, 0);
10865 }
10866 #endif
10867
10868
10869 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10870 void pic16_loadFSR0(operand *op, int lit)
10871 {
10872   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10873     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10874   } else {
10875     assert (!OP_SYMBOL(op)->remat);
10876     // set up FSR0 with address of result
10877     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10878     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10879   }
10880 }
10881
10882 /*-----------------------------------------------------------------*/
10883 /* genUnpackBits - generates code for unpacking bits               */
10884 /*-----------------------------------------------------------------*/
10885 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10886 {    
10887   int shCnt ;
10888   int rlen = 0 ;
10889   sym_link *etype, *letype;
10890   int blen=0, bstr=0;
10891   int lbstr;
10892   int offset = 0 ;
10893
10894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10895     etype = getSpec(operandType(result));
10896     letype = getSpec(operandType(left));
10897     
10898 //    if(IS_BITFIELD(etype)) {
10899       blen = SPEC_BLEN(etype);
10900       bstr = SPEC_BSTR(etype);
10901 //    }
10902
10903     lbstr = SPEC_BSTR( letype );
10904
10905 #if 1
10906     if((blen == 1) && (bstr < 8)) {
10907       /* it is a single bit, so use the appropriate bit instructions */
10908       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10909
10910       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10911       
10912       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10913       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10914         /* workaround to reduce the extra lfsr instruction */
10915         pic16_emitpcode(POC_BTFSC,
10916               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10917       } else {
10918         pic16_loadFSR0 (left, 0);
10919         pic16_emitpcode(POC_BTFSC,
10920               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10921       }
10922         
10923       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10924
10925       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10926       return;
10927     }
10928
10929 #endif
10930
10931         /* the following call to pic16_loadFSR0 is temporary until
10932          * optimization to handle single bit assignments is added
10933          * to the function. Until then use the old safe way! -- VR */
10934
10935     if (OP_SYMBOL(left)->remat) {
10936         // access symbol directly
10937         pic16_mov2w (AOP(left), 0);
10938     } else {
10939         pic16_loadFSR0( left, 0 );
10940  
10941         /* read the first byte  */
10942         switch (ptype) {
10943                 case POINTER:
10944                 case IPOINTER:
10945                 case PPOINTER:
10946                 case FPOINTER:
10947                 case GPOINTER:
10948                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10949                         break;
10950                 case CPOINTER:
10951                         pic16_emitcode("clr","a");
10952                         pic16_emitcode("movc","a","@a+dptr");
10953                         assert (0);
10954                         break;
10955         }
10956     }
10957
10958         /* if we have bitdisplacement then it fits   */
10959         /* into this byte completely or if length is */
10960         /* less than a byte                          */
10961         if ((shCnt = SPEC_BSTR(etype)) || 
10962                 (SPEC_BLEN(etype) <= 8))  {
10963
10964                 /* shift right acc */
10965                 AccRsh(shCnt, 0);
10966
10967                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10968                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10969
10970 /* VR -- normally I would use the following, but since we use the hack,
10971  * to avoid the masking from AccRsh, why not mask it right now? */
10972
10973 /*
10974                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10975 */
10976
10977                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10978           return ;
10979         }
10980
10981
10982
10983         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10984         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10985         exit(-1);
10986
10987     /* bit field did not fit in a byte  */
10988     rlen = SPEC_BLEN(etype) - 8;
10989     pic16_aopPut(AOP(result),"a",offset++);
10990
10991     while (1)  {
10992
10993         switch (ptype) {
10994         case POINTER:
10995         case IPOINTER:
10996             pic16_emitcode("inc","%s",rname);
10997             pic16_emitcode("mov","a,@%s",rname);
10998             break;
10999             
11000         case PPOINTER:
11001             pic16_emitcode("inc","%s",rname);
11002             pic16_emitcode("movx","a,@%s",rname);
11003             break;
11004
11005         case FPOINTER:
11006             pic16_emitcode("inc","dptr");
11007             pic16_emitcode("movx","a,@dptr");
11008             break;
11009             
11010         case CPOINTER:
11011             pic16_emitcode("clr","a");
11012             pic16_emitcode("inc","dptr");
11013             pic16_emitcode("movc","a","@a+dptr");
11014             break;
11015             
11016         case GPOINTER:
11017             pic16_emitcode("inc","dptr");
11018             pic16_emitcode("lcall","__gptrget");
11019             break;
11020         }
11021
11022         rlen -= 8;            
11023         /* if we are done */
11024         if ( rlen <= 0 )
11025             break ;
11026         
11027         pic16_aopPut(AOP(result),"a",offset++);
11028                               
11029     }
11030     
11031     if (rlen) {
11032         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11033         pic16_aopPut(AOP(result),"a",offset);          
11034     }
11035     
11036     return ;
11037 }
11038
11039
11040 static void genDataPointerGet(operand *left,
11041                               operand *result,
11042                               iCode *ic)
11043 {
11044   int size, offset = 0, leoffset=0 ;
11045
11046         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11047         pic16_aopOp(result, ic, TRUE);
11048
11049         size = AOP_SIZE(result);
11050 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11051
11052
11053 #if 0
11054         /* The following tests may save a redudant movff instruction when
11055          * accessing unions */
11056          
11057         /* if they are the same */
11058         if (operandsEqu (left, result)) {
11059                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11060                 goto release;
11061         }
11062 #endif
11063
11064 #if 0
11065         /* if they are the same registers */
11066         if (pic16_sameRegs(AOP(left),AOP(result))) {
11067                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11068                 goto release;
11069         }
11070 #endif
11071
11072 #if 1
11073         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11074                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11075                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11076                 goto release;
11077         }
11078 #endif
11079
11080
11081 #if 0
11082         if ( AOP_TYPE(left) == AOP_PCODE) {
11083                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11084                                 AOP(left)->aopu.pcop->name,
11085                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11086                                 PCOR(AOP(left)->aopu.pcop)->instance:
11087                                 PCOI(AOP(left)->aopu.pcop)->offset);
11088         }
11089 #endif
11090
11091         if(AOP(left)->aopu.pcop->type == PO_DIR)
11092                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11093
11094         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11095
11096         while (size--) {
11097                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11098                 
11099                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11100                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11101                         pic16_mov2w(AOP(left), offset); // patch 8
11102                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11103                 } else {
11104                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11105                                 pic16_popGet(AOP(left), offset), //patch 8
11106                                 pic16_popGet(AOP(result), offset)));
11107                 }
11108
11109                 offset++;
11110                 leoffset++;
11111         }
11112
11113 release:
11114     pic16_freeAsmop(result,NULL,ic,TRUE);
11115 }
11116
11117
11118
11119 /*-----------------------------------------------------------------*/
11120 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11121 /*-----------------------------------------------------------------*/
11122 static void genNearPointerGet (operand *left, 
11123                                operand *result, 
11124                                iCode *ic)
11125 {
11126 //  asmop *aop = NULL;
11127   //regs *preg = NULL ;
11128   sym_link *rtype, *retype;
11129   sym_link *ltype = operandType(left);    
11130
11131     FENTRY;
11132     
11133     rtype = operandType(result);
11134     retype= getSpec(rtype);
11135     
11136     pic16_aopOp(left,ic,FALSE);
11137
11138 //    pic16_DumpOp("(left)",left);
11139 //    pic16_DumpOp("(result)",result);
11140
11141     /* if left is rematerialisable and
11142      * result is not bit variable type and
11143      * the left is pointer to data space i.e
11144      * lower 128 bytes of space */
11145     
11146     if (AOP_TYPE(left) == AOP_PCODE
11147       && !IS_BITFIELD(retype)
11148       && DCL_TYPE(ltype) == POINTER) {
11149
11150         genDataPointerGet (left,result,ic);
11151         pic16_freeAsmop(left, NULL, ic, TRUE);
11152         return ;
11153     }
11154     
11155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11156     pic16_aopOp (result,ic,TRUE);
11157     
11158     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11159
11160 #if 1
11161     if(IS_BITFIELD( retype )
11162       && (SPEC_BLEN(operandType(result))==1)
11163     ) {
11164       iCode *nextic;
11165       pCodeOp *jop;
11166       int bitstrt, bytestrt;
11167
11168         /* if this is bitfield of size 1, see if we are checking the value
11169          * of a single bit in an if-statement,
11170          * if yes, then don't generate usual code, but execute the
11171          * genIfx directly -- VR */
11172
11173         nextic = ic->next;
11174
11175         /* CHECK: if next iCode is IFX
11176          * and current result operand is nextic's conditional operand
11177          * and current result operand live ranges ends at nextic's key number
11178          */
11179         if((nextic->op == IFX)
11180           && (result == IC_COND(nextic))
11181           && (OP_LIVETO(result) == nextic->seq)
11182           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11183           ) {
11184             /* everything is ok then */
11185             /* find a way to optimize the genIfx iCode */
11186
11187             bytestrt = SPEC_BSTR(operandType(result))/8;
11188             bitstrt = SPEC_BSTR(operandType(result))%8;
11189             
11190             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11191
11192             genIfxpCOpJump(nextic, jop);
11193             
11194             pic16_freeAsmop(left, NULL, ic, TRUE);
11195             pic16_freeAsmop(result, NULL, ic, TRUE);
11196             return;
11197         }
11198     }
11199 #endif
11200
11201
11202     /* if the value is already in a pointer register
11203      * then don't need anything more */
11204     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11205       /* otherwise get a free pointer register */
11206       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11207                 
11208       ;
11209     }
11210
11211     /* if bitfield then unpack the bits */
11212     if (IS_BITFIELD(retype)) 
11213       genUnpackBits (result, left, NULL, POINTER);
11214     else {
11215       /* we have can just get the values */
11216       int size = AOP_SIZE(result);
11217       int offset = 0;   
11218         
11219       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11220
11221       pic16_loadFSR0( left, 0 );
11222
11223       while(size--) {
11224         if(size) {
11225           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11226                 pic16_popGet(AOP(result), offset++)));
11227         } else {
11228           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11229                 pic16_popGet(AOP(result), offset++)));
11230         }
11231       }
11232     }
11233
11234 #if 0
11235     /* now some housekeeping stuff */
11236     if (aop) {
11237       /* we had to allocate for this iCode */
11238       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11239       pic16_freeAsmop(NULL,aop,ic,TRUE);
11240     } else { 
11241       /* we did not allocate which means left
11242        * already in a pointer register, then
11243        * if size > 0 && this could be used again
11244        * we have to point it back to where it 
11245        * belongs */
11246       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11247       if (AOP_SIZE(result) > 1
11248         && !OP_SYMBOL(left)->remat
11249         && ( OP_SYMBOL(left)->liveTo > ic->seq
11250             || ic->depth )) {
11251 //        int size = AOP_SIZE(result) - 1;
11252 //        while (size--)
11253 //          pic16_emitcode("dec","%s",rname);
11254         }
11255     }
11256 #endif
11257
11258     /* done */
11259     pic16_freeAsmop(left,NULL,ic,TRUE);
11260     pic16_freeAsmop(result,NULL,ic,TRUE);
11261 }
11262
11263 /*-----------------------------------------------------------------*/
11264 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11265 /*-----------------------------------------------------------------*/
11266 static void genPagedPointerGet (operand *left, 
11267                                operand *result, 
11268                                iCode *ic)
11269 {
11270     asmop *aop = NULL;
11271     regs *preg = NULL ;
11272     char *rname ;
11273     sym_link *rtype, *retype;    
11274
11275     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11276
11277     rtype = operandType(result);
11278     retype= getSpec(rtype);
11279     
11280     pic16_aopOp(left,ic,FALSE);
11281
11282   /* if the value is already in a pointer register
11283        then don't need anything more */
11284     if (!AOP_INPREG(AOP(left))) {
11285         /* otherwise get a free pointer register */
11286         aop = newAsmop(0);
11287         preg = getFreePtr(ic,&aop,FALSE);
11288         pic16_emitcode("mov","%s,%s",
11289                 preg->name,
11290                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11291         rname = preg->name ;
11292     } else
11293         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11294     
11295     pic16_freeAsmop(left,NULL,ic,TRUE);
11296     pic16_aopOp (result,ic,TRUE);
11297
11298     /* if bitfield then unpack the bits */
11299     if (IS_BITFIELD(retype)) 
11300         genUnpackBits (result,left,rname,PPOINTER);
11301     else {
11302         /* we have can just get the values */
11303         int size = AOP_SIZE(result);
11304         int offset = 0 ;        
11305         
11306         while (size--) {
11307             
11308             pic16_emitcode("movx","a,@%s",rname);
11309             pic16_aopPut(AOP(result),"a",offset);
11310             
11311             offset++ ;
11312             
11313             if (size)
11314                 pic16_emitcode("inc","%s",rname);
11315         }
11316     }
11317
11318     /* now some housekeeping stuff */
11319     if (aop) {
11320         /* we had to allocate for this iCode */
11321         pic16_freeAsmop(NULL,aop,ic,TRUE);
11322     } else { 
11323         /* we did not allocate which means left
11324            already in a pointer register, then
11325            if size > 0 && this could be used again
11326            we have to point it back to where it 
11327            belongs */
11328         if (AOP_SIZE(result) > 1 &&
11329             !OP_SYMBOL(left)->remat &&
11330             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11331               ic->depth )) {
11332             int size = AOP_SIZE(result) - 1;
11333             while (size--)
11334                 pic16_emitcode("dec","%s",rname);
11335         }
11336     }
11337
11338     /* done */
11339     pic16_freeAsmop(result,NULL,ic,TRUE);
11340     
11341         
11342 }
11343
11344 /*-----------------------------------------------------------------*/
11345 /* genFarPointerGet - gget value from far space                    */
11346 /*-----------------------------------------------------------------*/
11347 static void genFarPointerGet (operand *left,
11348                               operand *result, iCode *ic)
11349 {
11350     int size, offset ;
11351     sym_link *retype = getSpec(operandType(result));
11352
11353     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11354
11355     pic16_aopOp(left,ic,FALSE);
11356
11357     /* if the operand is already in dptr 
11358     then we do nothing else we move the value to dptr */
11359     if (AOP_TYPE(left) != AOP_STR) {
11360         /* if this is remateriazable */
11361         if (AOP_TYPE(left) == AOP_IMMD)
11362             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11363         else { /* we need to get it byte by byte */
11364             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11365             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11366             if (options.model == MODEL_FLAT24)
11367             {
11368                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11369             }
11370         }
11371     }
11372     /* so dptr know contains the address */
11373     pic16_freeAsmop(left,NULL,ic,TRUE);
11374     pic16_aopOp(result,ic,TRUE);
11375
11376     /* if bit then unpack */
11377     if (IS_BITFIELD(retype)) 
11378         genUnpackBits(result,left,"dptr",FPOINTER);
11379     else {
11380         size = AOP_SIZE(result);
11381         offset = 0 ;
11382
11383         while (size--) {
11384             pic16_emitcode("movx","a,@dptr");
11385             pic16_aopPut(AOP(result),"a",offset++);
11386             if (size)
11387                 pic16_emitcode("inc","dptr");
11388         }
11389     }
11390
11391     pic16_freeAsmop(result,NULL,ic,TRUE);
11392 }
11393
11394 #if 0
11395 /*-----------------------------------------------------------------*/
11396 /* genCodePointerGet - get value from code space                  */
11397 /*-----------------------------------------------------------------*/
11398 static void genCodePointerGet (operand *left,
11399                                 operand *result, iCode *ic)
11400 {
11401     int size, offset ;
11402     sym_link *retype = getSpec(operandType(result));
11403
11404     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11405
11406     pic16_aopOp(left,ic,FALSE);
11407
11408     /* if the operand is already in dptr 
11409     then we do nothing else we move the value to dptr */
11410     if (AOP_TYPE(left) != AOP_STR) {
11411         /* if this is remateriazable */
11412         if (AOP_TYPE(left) == AOP_IMMD)
11413             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11414         else { /* we need to get it byte by byte */
11415             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11416             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11417             if (options.model == MODEL_FLAT24)
11418             {
11419                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11420             }
11421         }
11422     }
11423     /* so dptr know contains the address */
11424     pic16_freeAsmop(left,NULL,ic,TRUE);
11425     pic16_aopOp(result,ic,FALSE);
11426
11427     /* if bit then unpack */
11428     if (IS_BITFIELD(retype)) 
11429         genUnpackBits(result,left,"dptr",CPOINTER);
11430     else {
11431         size = AOP_SIZE(result);
11432         offset = 0 ;
11433
11434         while (size--) {
11435             pic16_emitcode("clr","a");
11436             pic16_emitcode("movc","a,@a+dptr");
11437             pic16_aopPut(AOP(result),"a",offset++);
11438             if (size)
11439                 pic16_emitcode("inc","dptr");
11440         }
11441     }
11442
11443     pic16_freeAsmop(result,NULL,ic,TRUE);
11444 }
11445 #endif
11446
11447 #if 0
11448 /*-----------------------------------------------------------------*/
11449 /* genGenPointerGet - gget value from generic pointer space        */
11450 /*-----------------------------------------------------------------*/
11451 static void genGenPointerGet (operand *left,
11452                               operand *result, iCode *ic)
11453 {
11454   int size, offset, lit;
11455   sym_link *retype = getSpec(operandType(result));
11456
11457         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11458         pic16_aopOp(left,ic,FALSE);
11459         pic16_aopOp(result,ic,FALSE);
11460         size = AOP_SIZE(result);
11461
11462         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11463
11464         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11465
11466                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11467                 // load FSR0 from immediate
11468                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11469
11470 //              pic16_loadFSR0( left );
11471
11472                 offset = 0;
11473                 while(size--) {
11474                         if(size) {
11475                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11476                         } else {
11477                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11478                         }
11479                         offset++;
11480                 }
11481                 goto release;
11482
11483         }
11484         else { /* we need to get it byte by byte */
11485                 // set up FSR0 with address from left
11486                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11487                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11488                 
11489                 offset = 0 ;
11490
11491                 while(size--) {
11492                         if(size) {
11493                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11494                         } else {
11495                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11496                         }
11497                         offset++;
11498                 }
11499                 goto release;
11500         }
11501
11502   /* if bit then unpack */
11503         if (IS_BITFIELD(retype)) 
11504                 genUnpackBits(result,left,"BAD",GPOINTER);
11505
11506         release:
11507         pic16_freeAsmop(left,NULL,ic,TRUE);
11508         pic16_freeAsmop(result,NULL,ic,TRUE);
11509
11510 }
11511 #endif
11512
11513
11514 /*-----------------------------------------------------------------*/
11515 /* genGenPointerGet - gget value from generic pointer space        */
11516 /*-----------------------------------------------------------------*/
11517 static void genGenPointerGet (operand *left,
11518                               operand *result, iCode *ic)
11519 {
11520   int size, offset, lit;
11521   sym_link *retype = getSpec(operandType(result));
11522   char fgptrget[32];
11523
11524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11525     pic16_aopOp(left,ic,FALSE);
11526     pic16_aopOp(result,ic,TRUE);
11527     size = AOP_SIZE(result);
11528
11529     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11530
11531     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11532
11533       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11534       // load FSR0 from immediate
11535       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11536
11537       werror(W_POSSBUG2, __FILE__, __LINE__);
11538
11539       offset = 0;
11540       while(size--) {
11541         if(size) {
11542           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11543         } else {
11544           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11545         }
11546         offset++;
11547       }
11548
11549       goto release;
11550
11551     } else { /* we need to get it byte by byte */
11552
11553       /* set up WREG:PRODL:FSR0L with address from left */
11554       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11555       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11556       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11557       
11558       switch( size ) {
11559         case 1: strcpy(fgptrget, "__gptrget1"); break;
11560         case 2: strcpy(fgptrget, "__gptrget2"); break;
11561         case 3: strcpy(fgptrget, "__gptrget3"); break;
11562         case 4: strcpy(fgptrget, "__gptrget4"); break;
11563         default:
11564           werror(W_POSSBUG2, __FILE__, __LINE__);
11565           abort();
11566       }
11567       
11568       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11569       
11570       assignResultValue(result, 1);
11571       
11572       {
11573         symbol *sym;
11574
11575           sym = newSymbol( fgptrget, 0 );
11576           sym->used++;
11577           strcpy(sym->rname, fgptrget);
11578           checkAddSym(&externs, sym);
11579
11580 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11581       }
11582               
11583       goto release;
11584     }
11585
11586   /* if bit then unpack */
11587     if (IS_BITFIELD(retype)) 
11588       genUnpackBits(result,left,"BAD",GPOINTER);
11589
11590 release:
11591   pic16_freeAsmop(left,NULL,ic,TRUE);
11592   pic16_freeAsmop(result,NULL,ic,TRUE);
11593 }
11594
11595 /*-----------------------------------------------------------------*/
11596 /* genConstPointerGet - get value from const generic pointer space */
11597 /*-----------------------------------------------------------------*/
11598 static void genConstPointerGet (operand *left,
11599                                 operand *result, iCode *ic)
11600 {
11601   //sym_link *retype = getSpec(operandType(result));
11602   // symbol *albl = newiTempLabel(NULL);        // patch 15
11603   // symbol *blbl = newiTempLabel(NULL);        //
11604   // PIC_OPCODE poc;                            // patch 15
11605   int size;
11606   int offset = 0;
11607
11608   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11609   pic16_aopOp(left,ic,FALSE);
11610   pic16_aopOp(result,ic,TRUE);
11611   size = AOP_SIZE(result);
11612
11613   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11614
11615   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11616
11617   // set up table pointer
11618   if( (AOP_TYPE(left) == AOP_PCODE) 
11619       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11620           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11621     {
11622       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11623       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11624       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11625       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11626       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11627       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11628   } else {
11629     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11630     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11631     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11632   }
11633
11634   while(size--) {
11635     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11636     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11637     offset++;
11638   }
11639     
11640   pic16_freeAsmop(left,NULL,ic,TRUE);
11641   pic16_freeAsmop(result,NULL,ic,TRUE);
11642 }
11643
11644
11645 /*-----------------------------------------------------------------*/
11646 /* genPointerGet - generate code for pointer get                   */
11647 /*-----------------------------------------------------------------*/
11648 static void genPointerGet (iCode *ic)
11649 {
11650   operand *left, *result ;
11651   sym_link *type, *etype;
11652   int p_type;
11653
11654     FENTRY;
11655     
11656     left = IC_LEFT(ic);
11657     result = IC_RESULT(ic) ;
11658
11659     /* depending on the type of pointer we need to
11660     move it to the correct pointer register */
11661     type = operandType(left);
11662     etype = getSpec(type);
11663
11664 #if 0
11665     if (IS_PTR_CONST(type))
11666 #else
11667     if (IS_CODEPTR(type))
11668 #endif
11669       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11670
11671     /* if left is of type of pointer then it is simple */
11672     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11673       p_type = DCL_TYPE(type);
11674     else {
11675       /* we have to go by the storage class */
11676       p_type = PTR_TYPE(SPEC_OCLS(etype));
11677
11678       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11679
11680       if (SPEC_OCLS(etype)->codesp ) {
11681         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11682         //p_type = CPOINTER ;   
11683       } else
11684       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11685         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11686         /*p_type = FPOINTER ;*/ 
11687       } else
11688       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11689         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11690         /* p_type = PPOINTER; */
11691       } else
11692       if (SPEC_OCLS(etype) == idata ) {
11693         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11694         /* p_type = IPOINTER; */
11695       } else {
11696         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11697         /* p_type = POINTER ; */
11698       }
11699     }
11700
11701     /* now that we have the pointer type we assign
11702     the pointer values */
11703     switch (p_type) {
11704       case POINTER:     
11705       case IPOINTER:
11706         genNearPointerGet (left,result,ic);
11707         break;
11708
11709       case PPOINTER:
11710         genPagedPointerGet(left,result,ic);
11711         break;
11712
11713       case FPOINTER:
11714         genFarPointerGet (left,result,ic);
11715         break;
11716
11717       case CPOINTER:
11718         genConstPointerGet (left,result,ic);
11719         //pic16_emitcodePointerGet (left,result,ic);
11720         break;
11721
11722       case GPOINTER:
11723 #if 0
11724       if (IS_PTR_CONST(type))
11725         genConstPointerGet (left,result,ic);
11726       else
11727 #endif
11728         genGenPointerGet (left,result,ic);
11729       break;
11730
11731     default:
11732       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11733               "genPointerGet: illegal pointer type");
11734     
11735     }
11736 }
11737
11738 /*-----------------------------------------------------------------*/
11739 /* genPackBits - generates code for packed bit storage             */
11740 /*-----------------------------------------------------------------*/
11741 static void genPackBits (sym_link    *etype , operand *result,
11742                          operand *right ,
11743                          char *rname, int p_type)
11744 {
11745   int shCnt = 0 ;
11746   int offset = 0  ;
11747   int rLen = 0 ;
11748   int blen, bstr ;   
11749   sym_link *retype;
11750
11751         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11752         blen = SPEC_BLEN(etype);
11753         bstr = SPEC_BSTR(etype);
11754
11755         retype = getSpec(operandType(right));
11756
11757         if(AOP_TYPE(right) == AOP_LIT) {
11758                 if((blen == 1) && (bstr < 8)) {
11759                   unsigned long lit;
11760                         /* it is a single bit, so use the appropriate bit instructions */
11761
11762                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11763
11764                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11765 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11766                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11767                                 /* workaround to reduce the extra lfsr instruction */
11768                                 if(lit) {
11769                                         pic16_emitpcode(POC_BSF,
11770                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11771                                 } else {
11772                                         pic16_emitpcode(POC_BCF,
11773                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11774                                 }
11775                         } else {
11776                                 pic16_loadFSR0(result, 0);
11777                                 if(lit) {
11778                                         pic16_emitpcode(POC_BSF,
11779                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11780                                 } else {
11781                                         pic16_emitpcode(POC_BCF,
11782                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11783                                 }
11784                         }
11785         
11786                   return;
11787                 }
11788                 /* move literal to W */
11789                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11790                 offset++;
11791         } else
11792         if(IS_BITFIELD(retype) 
11793           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11794           && (blen == 1)) {
11795           int rblen, rbstr;
11796
11797             rblen = SPEC_BLEN( retype );
11798             rbstr = SPEC_BSTR( retype );
11799             
11800
11801             if(IS_BITFIELD(etype)) {
11802               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11803               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11804             } else {
11805               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11806             }
11807             
11808             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11809             
11810             if(IS_BITFIELD(etype)) {
11811               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11812             } else {
11813               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11814             }
11815
11816             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11817             
11818             return;
11819         } else {
11820           /* move right to W */
11821           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11822         }
11823
11824         /* if the bit length is less than or   */
11825         /* it exactly fits a byte then         */
11826         if((shCnt=SPEC_BSTR(etype))
11827                 || SPEC_BLEN(etype) <= 8 )  {
11828                 int fsr0_setup = 0;
11829
11830                 if (blen != 8 || bstr != 0) {
11831                   // we need to combine the value with the old value
11832                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11833
11834           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11835                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11836                 
11837                   /* shift left acc */
11838                   AccLsh(shCnt);
11839
11840                   /* using PRODH as a temporary register here */
11841                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11842
11843                  if (OP_SYMBOL(result)->remat) {
11844                    // access symbol directly
11845                    pic16_mov2w (AOP(result), 0);
11846                  } else {
11847                   /* get old value */
11848                   switch (p_type) {
11849                         case FPOINTER:
11850                         case POINTER:
11851                                 pic16_loadFSR0( result, 0 );
11852                                 fsr0_setup = 1;
11853                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11854 //                              pic16_emitcode ("mov","b,a");
11855 //                              pic16_emitcode("mov","a,@%s",rname);
11856                                 break;
11857
11858                         case GPOINTER:
11859                                 if (AOP(result)->aopu.aop_reg[2]) {
11860                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11861                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11862                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11863                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11864                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11865                                   {
11866                                     symbol *sym;
11867                                     sym = newSymbol( "__gptrget1", 0 );
11868                                     strcpy(sym->rname, "__gptrget1");
11869                                     checkAddSym(&externs, sym);
11870                                   }
11871                                 } else {
11872                                   // data pointer (just 2 byte given)
11873                                   pic16_loadFSR0( result, 0 );
11874                                   fsr0_setup = 1;
11875                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11876                                 }
11877                                 
11878                                 // warnings will be emitted below
11879                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11880                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11881                                 break;
11882
11883                         default:
11884                                 assert (0 && "invalid pointer type specified");
11885                                 break;
11886                   }
11887                  }
11888 #if 1
11889                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11890                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11891                                         (unsigned char)(0xff >> (8-bstr))) ));
11892                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11893                 } // if (blen != 8 || bstr != 0)
11894
11895                 /* write new value back */
11896                if (OP_SYMBOL(result)->remat) {
11897                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11898                } else {
11899                 switch (p_type) {
11900                         case FPOINTER:
11901                         case POINTER:
11902                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11903                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11904                                 break;
11905
11906                         case GPOINTER:
11907                                 if (AOP(result)->aopu.aop_reg[2]) {
11908                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11909                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11910                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11911                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11912                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11913                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11914                                   {
11915                                     symbol *sym;
11916                                     sym = newSymbol( "__gptrput1", 0 );
11917                                     strcpy(sym->rname, "__gptrput1");
11918                                     checkAddSym(&externs, sym);
11919                                   }
11920                                 } else {
11921                                   // data pointer (just 2 byte given)
11922                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11923                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11924                                 }
11925                                 
11926                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11927                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11928                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11929                                 break;
11930
11931                         default:
11932                                 assert (0 && "invalid pointer type specified");
11933                                 break;
11934                 }
11935                }
11936 #endif
11937
11938           return;
11939         }
11940
11941
11942 #if 0
11943         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11944         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11945         exit(-1);
11946 #endif
11947
11948
11949     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11950     rLen = SPEC_BLEN(etype)-8;
11951     
11952     /* now generate for lengths greater than one byte */
11953     while (1) {
11954         rLen -= 8 ;
11955         if (rLen <= 0 ) {
11956           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11957           break ;
11958         }
11959
11960         switch (p_type) {
11961             case POINTER:
11962                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11963                 break;
11964
11965 /*
11966             case FPOINTER:
11967                 MOVA(l);
11968                 pic16_emitcode("movx","@dptr,a");
11969                 break;
11970
11971             case GPOINTER:
11972                 MOVA(l);
11973                 DEBUGpic16_emitcode(";lcall","__gptrput");
11974                 break;  
11975 */
11976           default:
11977             assert(0);
11978         }   
11979
11980
11981         pic16_mov2w(AOP(right), offset++);
11982     }
11983
11984     /* last last was not complete */
11985     if (rLen)   {
11986         /* save the byte & read byte */
11987         switch (p_type) {
11988             case POINTER:
11989 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11990                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11991                 break;
11992
11993 /*
11994             case FPOINTER:
11995                 pic16_emitcode ("mov","b,a");
11996                 pic16_emitcode("movx","a,@dptr");
11997                 break;
11998
11999             case GPOINTER:
12000                 pic16_emitcode ("push","b");
12001                 pic16_emitcode ("push","acc");
12002                 pic16_emitcode ("lcall","__gptrget");
12003                 pic16_emitcode ("pop","b");
12004                 break;
12005 */
12006             default:
12007               assert(0);
12008         }
12009         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
12010         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
12011         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
12012 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
12013 //        pic16_emitcode ("orl","a,b");
12014     }
12015
12016 //    if (p_type == GPOINTER)
12017 //        pic16_emitcode("pop","b");
12018
12019     switch (p_type) {
12020
12021       case POINTER:
12022         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12023 //      pic16_emitcode("mov","@%s,a",rname);
12024         break;
12025 /*
12026       case FPOINTER:
12027         pic16_emitcode("movx","@dptr,a");
12028         break;
12029         
12030       case GPOINTER:
12031         DEBUGpic16_emitcode(";lcall","__gptrput");
12032         break;                  
12033 */
12034       default:
12035         assert(0);
12036     }
12037     
12038 //    pic16_freeAsmop(right, NULL, ic, TRUE);
12039 }
12040 /*-----------------------------------------------------------------*/
12041 /* genDataPointerSet - remat pointer to data space                 */
12042 /*-----------------------------------------------------------------*/
12043 static void genDataPointerSet(operand *right,
12044                               operand *result,
12045                               iCode *ic)
12046 {
12047     int size, offset = 0, resoffset=0 ;
12048
12049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12050     pic16_aopOp(right,ic,FALSE);
12051
12052     size = AOP_SIZE(right);
12053
12054 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12055
12056 #if 0
12057     if ( AOP_TYPE(result) == AOP_PCODE) {
12058       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12059               AOP(result)->aopu.pcop->name,
12060                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12061               PCOR(AOP(result)->aopu.pcop)->instance:
12062               PCOI(AOP(result)->aopu.pcop)->offset);
12063     }
12064 #endif
12065
12066         if(AOP(result)->aopu.pcop->type == PO_DIR)
12067                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12068
12069         while (size--) {
12070                 if (AOP_TYPE(right) == AOP_LIT) {
12071                   unsigned int lit;
12072
12073                     if(!IS_FLOAT(operandType( right )))
12074                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12075                     else {
12076                       union {
12077                         unsigned long lit_int;
12078                         float lit_float;
12079                       } info;
12080         
12081                         /* take care if literal is a float */
12082                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12083                         lit = info.lit_int;
12084                     }
12085
12086                     lit = lit >> (8*offset);
12087                     if(lit&0xff) {
12088                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12089                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12090                     } else {
12091                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12092                     }
12093                 } else {
12094                   pic16_mov2w(AOP(right), offset);
12095                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12096                 }
12097                 offset++;
12098                 resoffset++;
12099         }
12100
12101     pic16_freeAsmop(right,NULL,ic,TRUE);
12102 }
12103
12104
12105
12106 /*-----------------------------------------------------------------*/
12107 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12108 /*-----------------------------------------------------------------*/
12109 static void genNearPointerSet (operand *right,
12110                                operand *result, 
12111                                iCode *ic)
12112 {
12113   asmop *aop = NULL;
12114   sym_link *retype;
12115   sym_link *ptype = operandType(result);
12116   sym_link *resetype;
12117     
12118         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12119         retype= getSpec(operandType(right));
12120         resetype = getSpec(operandType(result));
12121   
12122         pic16_aopOp(result,ic,FALSE);
12123     
12124         /* if the result is rematerializable &
12125          * in data space & not a bit variable */
12126         
12127         /* and result is not a bit variable */
12128         if (AOP_TYPE(result) == AOP_PCODE
12129 //              && AOP_TYPE(result) == AOP_IMMD
12130                 && DCL_TYPE(ptype) == POINTER
12131                 && !IS_BITFIELD(retype)
12132                 && !IS_BITFIELD(resetype)) {
12133
12134                 genDataPointerSet (right,result,ic);
12135                 pic16_freeAsmop(result,NULL,ic,TRUE);
12136           return;
12137         }
12138
12139         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12140         pic16_aopOp(right,ic,FALSE);
12141         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12142
12143         /* if the value is already in a pointer register
12144          * then don't need anything more */
12145         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12146           /* otherwise get a free pointer register */
12147           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12148
12149           ;
12150         }
12151
12152         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12153
12154         /* if bitfield then unpack the bits */
12155         if (IS_BITFIELD(resetype)) {
12156                 genPackBits (resetype, result, right, NULL, POINTER);
12157         } else {
12158                 /* we have can just get the values */
12159           int size = AOP_SIZE(right);
12160           int offset = 0 ;    
12161
12162             pic16_loadFSR0(result, 0);
12163             
12164                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12165                 while (size--) {
12166                                 if (AOP_TYPE(right) == AOP_LIT) {
12167                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12168                                         if (size) {
12169                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12170                                         } else {
12171                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12172                                         }
12173                                 } else { // no literal
12174                                         if(size) {
12175                                                 pic16_emitpcode(POC_MOVFF,
12176                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12177                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12178                                         } else {
12179                                                 pic16_emitpcode(POC_MOVFF,
12180                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12181                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12182                                         }
12183                                 }
12184                         offset++;
12185                 }
12186         }
12187
12188         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12189         /* now some housekeeping stuff */
12190         if (aop) {
12191           /* we had to allocate for this iCode */
12192           pic16_freeAsmop(NULL,aop,ic,TRUE);
12193         } else { 
12194           /* we did not allocate which means left
12195            * already in a pointer register, then
12196            * if size > 0 && this could be used again
12197            * we have to point it back to where it 
12198            * belongs */
12199           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12200           if (AOP_SIZE(right) > 1
12201             && !OP_SYMBOL(result)->remat
12202             && ( OP_SYMBOL(result)->liveTo > ic->seq
12203             || ic->depth )) {
12204
12205               int size = AOP_SIZE(right) - 1;
12206
12207                 while (size--)
12208                   pic16_emitcode("decf","fsr0,f");
12209                   //pic16_emitcode("dec","%s",rname);
12210             }
12211         }
12212
12213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12214     /* done */
12215 //release:
12216     pic16_freeAsmop(right,NULL,ic,TRUE);
12217     pic16_freeAsmop(result,NULL,ic,TRUE);
12218 }
12219
12220 /*-----------------------------------------------------------------*/
12221 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12222 /*-----------------------------------------------------------------*/
12223 static void genPagedPointerSet (operand *right,
12224                                operand *result, 
12225                                iCode *ic)
12226 {
12227     asmop *aop = NULL;
12228     regs *preg = NULL ;
12229     char *rname , *l;
12230     sym_link *retype;
12231        
12232     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12233
12234     retype= getSpec(operandType(right));
12235     
12236     pic16_aopOp(result,ic,FALSE);
12237     
12238     /* if the value is already in a pointer register
12239        then don't need anything more */
12240     if (!AOP_INPREG(AOP(result))) {
12241         /* otherwise get a free pointer register */
12242         aop = newAsmop(0);
12243         preg = getFreePtr(ic,&aop,FALSE);
12244         pic16_emitcode("mov","%s,%s",
12245                 preg->name,
12246                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12247         rname = preg->name ;
12248     } else
12249         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12250     
12251     pic16_freeAsmop(result,NULL,ic,TRUE);
12252     pic16_aopOp (right,ic,FALSE);
12253
12254     /* if bitfield then unpack the bits */
12255     if (IS_BITFIELD(retype)) 
12256         genPackBits (retype,result,right,rname,PPOINTER);
12257     else {
12258         /* we have can just get the values */
12259         int size = AOP_SIZE(right);
12260         int offset = 0 ;        
12261         
12262         while (size--) {
12263             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12264             
12265             MOVA(l);
12266             pic16_emitcode("movx","@%s,a",rname);
12267
12268             if (size)
12269                 pic16_emitcode("inc","%s",rname);
12270
12271             offset++;
12272         }
12273     }
12274     
12275     /* now some housekeeping stuff */
12276     if (aop) {
12277         /* we had to allocate for this iCode */
12278         pic16_freeAsmop(NULL,aop,ic,TRUE);
12279     } else { 
12280         /* we did not allocate which means left
12281            already in a pointer register, then
12282            if size > 0 && this could be used again
12283            we have to point it back to where it 
12284            belongs */
12285         if (AOP_SIZE(right) > 1 &&
12286             !OP_SYMBOL(result)->remat &&
12287             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12288               ic->depth )) {
12289             int size = AOP_SIZE(right) - 1;
12290             while (size--)
12291                 pic16_emitcode("dec","%s",rname);
12292         }
12293     }
12294
12295     /* done */
12296     pic16_freeAsmop(right,NULL,ic,TRUE);
12297     
12298         
12299 }
12300
12301 /*-----------------------------------------------------------------*/
12302 /* genFarPointerSet - set value from far space                     */
12303 /*-----------------------------------------------------------------*/
12304 static void genFarPointerSet (operand *right,
12305                               operand *result, iCode *ic)
12306 {
12307     int size, offset ;
12308     sym_link *retype = getSpec(operandType(right));
12309
12310     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12311     pic16_aopOp(result,ic,FALSE);
12312
12313     /* if the operand is already in dptr 
12314     then we do nothing else we move the value to dptr */
12315     if (AOP_TYPE(result) != AOP_STR) {
12316         /* if this is remateriazable */
12317         if (AOP_TYPE(result) == AOP_IMMD)
12318             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12319         else { /* we need to get it byte by byte */
12320             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12321             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12322             if (options.model == MODEL_FLAT24)
12323             {
12324                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12325             }
12326         }
12327     }
12328     /* so dptr know contains the address */
12329     pic16_freeAsmop(result,NULL,ic,TRUE);
12330     pic16_aopOp(right,ic,FALSE);
12331
12332     /* if bit then unpack */
12333     if (IS_BITFIELD(retype)) 
12334         genPackBits(retype,result,right,"dptr",FPOINTER);
12335     else {
12336         size = AOP_SIZE(right);
12337         offset = 0 ;
12338
12339         while (size--) {
12340             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12341             MOVA(l);
12342             pic16_emitcode("movx","@dptr,a");
12343             if (size)
12344                 pic16_emitcode("inc","dptr");
12345         }
12346     }
12347
12348     pic16_freeAsmop(right,NULL,ic,TRUE);
12349 }
12350
12351 /*-----------------------------------------------------------------*/
12352 /* genGenPointerSet - set value from generic pointer space         */
12353 /*-----------------------------------------------------------------*/
12354 #if 0
12355 static void genGenPointerSet (operand *right,
12356                               operand *result, iCode *ic)
12357 {
12358         int i, size, offset, lit;
12359         sym_link *retype = getSpec(operandType(right));
12360
12361         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12362
12363         pic16_aopOp(result,ic,FALSE);
12364         pic16_aopOp(right,ic,FALSE);
12365         size = AOP_SIZE(right);
12366         offset = 0;
12367
12368         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12369
12370         /* if the operand is already in dptr 
12371                 then we do nothing else we move the value to dptr */
12372         if (AOP_TYPE(result) != AOP_STR) {
12373                 /* if this is remateriazable */
12374                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12375                 // WARNING: anythig until "else" is untested!
12376                 if (AOP_TYPE(result) == AOP_IMMD) {
12377                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12378                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12379                         // load FSR0 from immediate
12380                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12381                         offset = 0;
12382                         while(size--) {
12383                                 if(size) {
12384                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12385                                 } else {
12386                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12387                                 }
12388                                 offset++;
12389                         }
12390                         goto release;
12391                 }
12392                 else { /* we need to get it byte by byte */
12393                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12394                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12395
12396                         // set up FSR0 with address of result
12397                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12398                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12399
12400                         /* hack hack! see if this the FSR. If so don't load W */
12401                         if(AOP_TYPE(right) != AOP_ACC) {
12402
12403                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12404
12405                                 if(AOP_TYPE(right) == AOP_LIT)
12406                                 {
12407                                         // copy literal
12408                                         // note: pic16_popGet handles sign extension
12409                                         for(i=0;i<size;i++) {
12410                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12411                                                 if(i < size-1)
12412                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12413                                                 else
12414                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12415                                         }
12416                                 } else {
12417                                         // copy regs
12418
12419                                         for(i=0;i<size;i++) {
12420                                                 if(i < size-1)
12421                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12422                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12423                                                 else
12424                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12425                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12426                                         }
12427                                 }
12428                                 goto release;
12429                         } 
12430                         // right = ACC
12431                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12432                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12433                         goto release;
12434         } // if (AOP_TYPE(result) != AOP_IMMD)
12435
12436         } // if (AOP_TYPE(result) != AOP_STR)
12437         /* so dptr know contains the address */
12438
12439
12440         /* if bit then unpack */
12441         if (IS_BITFIELD(retype)) 
12442                 genPackBits(retype,result,right,"dptr",GPOINTER);
12443         else {
12444                 size = AOP_SIZE(right);
12445                 offset = 0 ;
12446
12447                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12448
12449                 // set up FSR0 with address of result
12450                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12451                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12452         
12453                 while (size--) {
12454                         if (AOP_TYPE(right) == AOP_LIT) {
12455                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12456                                 if (size) {
12457                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12458                                 } else {
12459                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12460                                 }
12461                         } else { // no literal
12462                                 if(size) {
12463                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12464                                 } else {
12465                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12466                                 }
12467                         }
12468                         offset++;
12469                 }
12470         }
12471
12472         release:
12473         pic16_freeAsmop(right,NULL,ic,TRUE);
12474         pic16_freeAsmop(result,NULL,ic,TRUE);
12475 }
12476 #endif
12477
12478 static void genGenPointerSet (operand *right,
12479                               operand *result, iCode *ic)
12480 {
12481   int size;
12482   sym_link *retype = getSpec(operandType(right));
12483   char fgptrput[32];
12484
12485     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12486
12487     pic16_aopOp(result,ic,FALSE);
12488     pic16_aopOp(right,ic,FALSE);
12489     size = AOP_SIZE(right);
12490
12491     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12492
12493
12494     /* if bit then unpack */
12495     if (IS_BITFIELD(retype)) {
12496 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12497       genPackBits(retype,result,right,"dptr",GPOINTER);
12498       goto release;
12499     }
12500
12501     size = AOP_SIZE(right);
12502
12503     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12504
12505
12506
12507     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12508
12509     /* value of right+0 is placed on stack, which will be retrieved
12510      * by the support function this restoring the stack. The important
12511      * thing is that there is no need to manually restore stack pointer
12512      * here */
12513     pushaop(AOP(right), 0);
12514 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12515     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12516     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12517     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12518     
12519     /* load address to write to in WREG:FSR0H:FSR0L */
12520     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12521                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12522     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12523                                 pic16_popCopyReg(&pic16_pc_prodl)));
12524     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12525     
12526
12527     /* put code here */
12528     switch (size) {
12529       case 1: strcpy(fgptrput, "__gptrput1"); break;
12530       case 2: strcpy(fgptrput, "__gptrput2"); break;
12531       case 3: strcpy(fgptrput, "__gptrput3"); break;
12532       case 4: strcpy(fgptrput, "__gptrput4"); break;
12533       default:
12534         werror(W_POSSBUG2, __FILE__, __LINE__);
12535         abort();
12536     }
12537     
12538     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12539     
12540     {
12541       symbol *sym;
12542                   
12543         sym = newSymbol( fgptrput, 0 );
12544         sym->used++;
12545         strcpy(sym->rname, fgptrput);
12546         checkAddSym(&externs, sym);
12547     }
12548
12549 release:
12550     pic16_freeAsmop(right,NULL,ic,TRUE);
12551     pic16_freeAsmop(result,NULL,ic,TRUE);
12552 }
12553
12554 /*-----------------------------------------------------------------*/
12555 /* genPointerSet - stores the value into a pointer location        */
12556 /*-----------------------------------------------------------------*/
12557 static void genPointerSet (iCode *ic)
12558 {    
12559   operand *right, *result ;
12560   sym_link *type, *etype;
12561   int p_type;
12562
12563     FENTRY;
12564
12565     right = IC_RIGHT(ic);
12566     result = IC_RESULT(ic) ;
12567
12568     /* depending on the type of pointer we need to
12569     move it to the correct pointer register */
12570     type = operandType(result);
12571     etype = getSpec(type);
12572     /* if left is of type of pointer then it is simple */
12573     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12574         p_type = DCL_TYPE(type);
12575     }
12576     else {
12577         /* we have to go by the storage class */
12578         p_type = PTR_TYPE(SPEC_OCLS(etype));
12579
12580 /*      if (SPEC_OCLS(etype)->codesp ) { */
12581 /*          p_type = CPOINTER ;  */
12582 /*      } */
12583 /*      else */
12584 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12585 /*              p_type = FPOINTER ; */
12586 /*          else */
12587 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12588 /*                  p_type = PPOINTER ; */
12589 /*              else */
12590 /*                  if (SPEC_OCLS(etype) == idata ) */
12591 /*                      p_type = IPOINTER ; */
12592 /*                  else */
12593 /*                      p_type = POINTER ; */
12594     }
12595
12596     /* now that we have the pointer type we assign
12597     the pointer values */
12598     switch (p_type) {
12599       case POINTER:
12600       case IPOINTER:
12601         genNearPointerSet (right,result,ic);
12602         break;
12603
12604       case PPOINTER:
12605         genPagedPointerSet (right,result,ic);
12606         break;
12607
12608       case FPOINTER:
12609         genFarPointerSet (right,result,ic);
12610         break;
12611         
12612       case GPOINTER:
12613         genGenPointerSet (right,result,ic);
12614         break;
12615
12616       default:
12617         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12618           "genPointerSet: illegal pointer type");
12619     }
12620 }
12621
12622 /*-----------------------------------------------------------------*/
12623 /* genIfx - generate code for Ifx statement                        */
12624 /*-----------------------------------------------------------------*/
12625 static void genIfx (iCode *ic, iCode *popIc)
12626 {
12627   operand *cond = IC_COND(ic);
12628   int isbit =0;
12629
12630     FENTRY;
12631
12632     pic16_aopOp(cond,ic,FALSE);
12633
12634     /* get the value into acc */
12635     if (AOP_TYPE(cond) != AOP_CRY)
12636       pic16_toBoolean(cond);
12637     else
12638       isbit = 1;
12639     /* the result is now in the accumulator */
12640     pic16_freeAsmop(cond,NULL,ic,TRUE);
12641
12642     /* if there was something to be popped then do it */
12643     if (popIc)
12644       genIpop(popIc);
12645
12646     /* if the condition is  a bit variable */
12647     if (isbit && IS_ITEMP(cond) && 
12648         SPIL_LOC(cond)) {
12649       genIfxJump(ic,"c");
12650       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12651     } else {
12652       if (isbit && !IS_ITEMP(cond))
12653         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12654         else
12655         genIfxJump(ic,"a");
12656     }
12657     ic->generated = 1;
12658 }
12659
12660 /*-----------------------------------------------------------------*/
12661 /* genAddrOf - generates code for address of                       */
12662 /*-----------------------------------------------------------------*/
12663 static void genAddrOf (iCode *ic)
12664 {
12665   operand *result, *left;
12666   int size;
12667   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12668   pCodeOp *pcop0, *pcop1, *pcop2;
12669
12670     FENTRY;
12671
12672     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12673
12674     sym = OP_SYMBOL( IC_LEFT(ic) );
12675     
12676     if(sym->onStack) {
12677       /* get address of symbol on stack */
12678       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12679 #if 0
12680       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12681                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12682 #endif
12683
12684       // operands on stack are accessible via "FSR2 + index" with index
12685       // starting at 2 for arguments and growing from 0 downwards for
12686       // local variables (index == 0 is not assigned so we add one here)
12687       {
12688         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12689         if (soffs <= 0) {
12690           assert (soffs < 0);
12691           soffs++;
12692         } // if
12693         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12694         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12695         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12696         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12697         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12698         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12699         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12700       }
12701
12702       goto release;
12703     }
12704         
12705 //      if(pic16_debug_verbose) {
12706 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12707 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12708 //      }
12709         
12710     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12711     size = AOP_SIZE(IC_RESULT(ic));
12712
12713     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12714     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12715     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12716         
12717     if (size == 3) {
12718       pic16_emitpcode(POC_MOVLW, pcop0);
12719       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12720       pic16_emitpcode(POC_MOVLW, pcop1);
12721       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12722       pic16_emitpcode(POC_MOVLW, pcop2);
12723       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12724     } else
12725     if (size == 2) {
12726       pic16_emitpcode(POC_MOVLW, pcop0);
12727       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12728       pic16_emitpcode(POC_MOVLW, pcop1);
12729     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12730     } else {
12731       pic16_emitpcode(POC_MOVLW, pcop0);
12732       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12733     }
12734
12735     pic16_freeAsmop(left, NULL, ic, FALSE);
12736 release:
12737     pic16_freeAsmop(result,NULL,ic,TRUE);
12738 }
12739
12740
12741 #if 0
12742 /*-----------------------------------------------------------------*/
12743 /* genFarFarAssign - assignment when both are in far space         */
12744 /*-----------------------------------------------------------------*/
12745 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12746 {
12747     int size = AOP_SIZE(right);
12748     int offset = 0;
12749     char *l ;
12750     /* first push the right side on to the stack */
12751     while (size--) {
12752         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12753         MOVA(l);
12754         pic16_emitcode ("push","acc");
12755     }
12756     
12757     pic16_freeAsmop(right,NULL,ic,FALSE);
12758     /* now assign DPTR to result */
12759     pic16_aopOp(result,ic,FALSE);
12760     size = AOP_SIZE(result);
12761     while (size--) {
12762         pic16_emitcode ("pop","acc");
12763         pic16_aopPut(AOP(result),"a",--offset);
12764     }
12765     pic16_freeAsmop(result,NULL,ic,FALSE);
12766         
12767 }
12768 #endif
12769
12770 /*-----------------------------------------------------------------*/
12771 /* genAssign - generate code for assignment                        */
12772 /*-----------------------------------------------------------------*/
12773 static void genAssign (iCode *ic)
12774 {
12775   operand *result, *right;
12776   int size, offset,know_W;
12777   unsigned long lit = 0L;
12778
12779   result = IC_RESULT(ic);
12780   right  = IC_RIGHT(ic) ;
12781
12782   FENTRY;
12783   
12784   /* if they are the same */
12785   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12786     return ;
12787
12788   /* reversed order operands are aopOp'ed so that result operand
12789    * is effective in case right is a stack symbol. This maneauver
12790    * allows to use the _G.resDirect flag later */
12791   pic16_aopOp(result,ic,TRUE);
12792   pic16_aopOp(right,ic,FALSE);
12793
12794   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12795
12796   /* if they are the same registers */
12797   if (pic16_sameRegs(AOP(right),AOP(result)))
12798     goto release;
12799
12800   /* if the result is a bit */
12801   if (AOP_TYPE(result) == AOP_CRY) {
12802     /* if the right size is a literal then
12803        we know what the value is */
12804     if (AOP_TYPE(right) == AOP_LIT) {
12805           
12806       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12807                   pic16_popGet(AOP(result),0));
12808
12809       if (((int) operandLitValue(right))) 
12810         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12811                        AOP(result)->aopu.aop_dir,
12812                        AOP(result)->aopu.aop_dir);
12813       else
12814         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12815                        AOP(result)->aopu.aop_dir,
12816                        AOP(result)->aopu.aop_dir);
12817       goto release;
12818     }
12819
12820     /* the right is also a bit variable */
12821     if (AOP_TYPE(right) == AOP_CRY) {
12822       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12823       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12824       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12825
12826       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12827                      AOP(result)->aopu.aop_dir,
12828                      AOP(result)->aopu.aop_dir);
12829       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12830                      AOP(right)->aopu.aop_dir,
12831                      AOP(right)->aopu.aop_dir);
12832       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12833                      AOP(result)->aopu.aop_dir,
12834                      AOP(result)->aopu.aop_dir);
12835       goto release ;
12836     }
12837
12838     /* we need to or */
12839     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12840     pic16_toBoolean(right);
12841     emitSKPZ;
12842     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12843     //pic16_aopPut(AOP(result),"a",0);
12844     goto release ;
12845   }
12846
12847   /* bit variables done */
12848   /* general case */
12849   size = AOP_SIZE(result);
12850   offset = 0 ;
12851
12852   if(AOP_TYPE(right) == AOP_LIT) {
12853         if(!IS_FLOAT(operandType( right )))
12854                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12855         else {
12856            union {
12857               unsigned long lit_int;
12858               float lit_float;
12859             } info;
12860         
12861                 /* take care if literal is a float */
12862                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12863                 lit = info.lit_int;
12864         }
12865   }
12866
12867 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12868 //                      sizeof(unsigned long int), sizeof(float));
12869
12870
12871   if (AOP_TYPE(right) == AOP_REG) {
12872     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12873     while (size--) {
12874       
12875       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12876     } // while
12877     goto release;
12878   }
12879
12880   if(AOP_TYPE(right) != AOP_LIT
12881         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12882         && !IS_FUNC(OP_SYM_TYPE(right))
12883         ) {
12884         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12885         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12886
12887         // set up table pointer
12888         if(is_LitOp(right)) {
12889 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12890                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12891                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12892                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12893                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12894                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12895                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12896         } else {
12897 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12898                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12899                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12900                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12901                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12902                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12903                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12904         }
12905
12906         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12907         while(size--) {
12908                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12909                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12910                         pic16_popGet(AOP(result),offset)));
12911                 offset++;
12912         }
12913
12914         size = getSize(OP_SYM_ETYPE(right));
12915         if(AOP_SIZE(result) > size) {
12916                 size = AOP_SIZE(result) - size;
12917                 while(size--) {
12918                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12919                         offset++;
12920                 }
12921         }
12922         goto release;
12923   }
12924
12925
12926
12927 #if 0
12928 /* VR - What is this?! */
12929   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12930     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12931     if(aopIdx(AOP(result),0) == 4) {
12932
12933       /* this is a workaround to save value of right into wreg too,
12934        * value of wreg is going to be used later */
12935       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12936       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12937       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12938       goto release;
12939     } else
12940 //      assert(0);
12941       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12942   }
12943 #endif
12944
12945   know_W=-1;
12946   while (size--) {
12947   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12948     if(AOP_TYPE(right) == AOP_LIT) {
12949       if(lit&0xff) {
12950         if(know_W != (lit&0xff))
12951           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12952         know_W = lit&0xff;
12953         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12954       } else
12955         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12956
12957       lit >>= 8;
12958
12959     } else if (AOP_TYPE(right) == AOP_CRY) {
12960       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12961       if(offset == 0) {
12962         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12963         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12964         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12965       }
12966     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12967         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12968         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12969     } else {
12970       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12971
12972       if(!_G.resDirect)         /* use this aopForSym feature */
12973         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12974     }
12975             
12976     offset++;
12977   }
12978   
12979  release:
12980   pic16_freeAsmop (right,NULL,ic,FALSE);
12981   pic16_freeAsmop (result,NULL,ic,TRUE);
12982 }   
12983
12984 /*-----------------------------------------------------------------*/
12985 /* genJumpTab - generates code for jump table                       */
12986 /*-----------------------------------------------------------------*/
12987 static void genJumpTab (iCode *ic)
12988 {
12989   symbol *jtab;
12990   char *l;
12991   pCodeOp *jt_offs;
12992   pCodeOp *jt_offs_hi;
12993   pCodeOp *jt_label;
12994
12995     FENTRY;
12996
12997     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12998     /* get the condition into accumulator */
12999     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
13000     MOVA(l);
13001     /* multiply by three */
13002     pic16_emitcode("add","a,acc");
13003     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
13004
13005     jtab = newiTempLabel(NULL);
13006     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
13007     pic16_emitcode("jmp","@a+dptr");
13008     pic16_emitcode("","%05d_DS_:",jtab->key+100);
13009
13010 #if 0
13011     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
13012     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
13013     emitSKPNC;
13014     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
13015     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
13016     pic16_emitpLabel(jtab->key);
13017
13018 #else
13019
13020     jt_offs = pic16_popGetTempReg(0);
13021     jt_offs_hi = pic16_popGetTempReg(1);
13022     jt_label = pic16_popGetLabel (jtab->key);
13023     //fprintf (stderr, "Creating jump table...\n");
13024
13025     // calculate offset into jump table (idx * sizeof (GOTO))
13026     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
13027     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13028     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13029     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13030     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13031     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13032     pic16_emitpcode(POC_MOVWF , jt_offs);
13033
13034     // prepare PCLATx (set to first entry in jump table)
13035     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13036     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13037     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13038     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13039     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13040
13041     // set PCLATx to selected entry (new PCL is stored in jt_offs)
13042     pic16_emitpcode(POC_ADDWF , jt_offs);
13043     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13044     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13045     emitSKPNC;
13046     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
13047
13048     // release temporaries and prepare jump into table (new PCL --> WREG)
13049     pic16_emitpcode(POC_MOVFW , jt_offs);
13050     pic16_popReleaseTempReg (jt_offs_hi, 1);
13051     pic16_popReleaseTempReg (jt_offs, 0);
13052
13053     // jump into the table
13054     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13055
13056     pic16_emitpLabelFORCE(jtab->key);
13057
13058 #endif
13059     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13060
13061     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13062     /* now generate the jump labels */
13063     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13064          jtab = setNextItem(IC_JTLABELS(ic))) {
13065 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13066         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13067         
13068     }
13069     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13070
13071 }
13072
13073 /*-----------------------------------------------------------------*/
13074 /* genMixedOperation - gen code for operators between mixed types  */
13075 /*-----------------------------------------------------------------*/
13076 /*
13077   TSD - Written for the PIC port - but this unfortunately is buggy.
13078   This routine is good in that it is able to efficiently promote 
13079   types to different (larger) sizes. Unfortunately, the temporary
13080   variables that are optimized out by this routine are sometimes
13081   used in other places. So until I know how to really parse the 
13082   iCode tree, I'm going to not be using this routine :(.
13083 */
13084 static int genMixedOperation (iCode *ic)
13085 {
13086 #if 0
13087   operand *result = IC_RESULT(ic);
13088   sym_link *ctype = operandType(IC_LEFT(ic));
13089   operand *right = IC_RIGHT(ic);
13090   int ret = 0;
13091   int big,small;
13092   int offset;
13093
13094   iCode *nextic;
13095   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13096
13097   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13098
13099   nextic = ic->next;
13100   if(!nextic)
13101     return 0;
13102
13103   nextright = IC_RIGHT(nextic);
13104   nextleft  = IC_LEFT(nextic);
13105   nextresult = IC_RESULT(nextic);
13106
13107   pic16_aopOp(right,ic,FALSE);
13108   pic16_aopOp(result,ic,FALSE);
13109   pic16_aopOp(nextright,  nextic, FALSE);
13110   pic16_aopOp(nextleft,   nextic, FALSE);
13111   pic16_aopOp(nextresult, nextic, FALSE);
13112
13113   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13114
13115     operand *t = right;
13116     right = nextright;
13117     nextright = t; 
13118
13119     pic16_emitcode(";remove right +","");
13120
13121   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13122 /*
13123     operand *t = right;
13124     right = nextleft;
13125     nextleft = t; 
13126 */
13127     pic16_emitcode(";remove left +","");
13128   } else
13129     return 0;
13130
13131   big = AOP_SIZE(nextleft);
13132   small = AOP_SIZE(nextright);
13133
13134   switch(nextic->op) {
13135
13136   case '+':
13137     pic16_emitcode(";optimize a +","");
13138     /* if unsigned or not an integral type */
13139     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13140       pic16_emitcode(";add a bit to something","");
13141     } else {
13142
13143       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13144
13145       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13146         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13147         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13148       } else
13149         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13150
13151       offset = 0;
13152       while(--big) {
13153
13154         offset++;
13155
13156         if(--small) {
13157           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13158             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13159             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13160           }
13161
13162           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13163           emitSKPNC;
13164           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13165                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13166                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13167           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13168           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13169
13170         } else {
13171           pic16_emitcode("rlf","known_zero,w");
13172
13173           /*
13174             if right is signed
13175               btfsc  right,7
13176                addlw ff
13177           */
13178           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13179             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13180             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13181           } else {
13182             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13183           }
13184         }
13185       }
13186       ret = 1;
13187     }
13188   }
13189   ret = 1;
13190
13191 release:
13192   pic16_freeAsmop(right,NULL,ic,TRUE);
13193   pic16_freeAsmop(result,NULL,ic,TRUE);
13194   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13195   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13196   if(ret)
13197     nextic->generated = 1;
13198
13199   return ret;
13200 #else
13201   return 0;
13202 #endif
13203 }
13204 /*-----------------------------------------------------------------*/
13205 /* genCast - gen code for casting                                  */
13206 /*-----------------------------------------------------------------*/
13207 static void genCast (iCode *ic)
13208 {
13209   operand *result = IC_RESULT(ic);
13210   sym_link *ctype = operandType(IC_LEFT(ic));
13211   sym_link *rtype = operandType(IC_RIGHT(ic));
13212   sym_link *restype = operandType(IC_RESULT(ic));
13213   operand *right = IC_RIGHT(ic);
13214   int size, offset ;
13215
13216
13217     FENTRY;
13218
13219         /* if they are equivalent then do nothing */
13220 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13221 //              return ;
13222
13223         pic16_aopOp(right,ic,FALSE) ;
13224         pic16_aopOp(result,ic,FALSE);
13225
13226         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13227
13228
13229         /* if the result is a bit */
13230         if (AOP_TYPE(result) == AOP_CRY) {
13231         
13232                 /* if the right size is a literal then
13233                  * we know what the value is */
13234                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13235
13236                 if (AOP_TYPE(right) == AOP_LIT) {
13237                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13238                                 pic16_popGet(AOP(result),0));
13239
13240                         if (((int) operandLitValue(right))) 
13241                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13242                                         AOP(result)->aopu.aop_dir,
13243                                         AOP(result)->aopu.aop_dir);
13244                         else
13245                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13246                                         AOP(result)->aopu.aop_dir,
13247                                         AOP(result)->aopu.aop_dir);
13248                         goto release;
13249                 }
13250
13251                 /* the right is also a bit variable */
13252                 if (AOP_TYPE(right) == AOP_CRY) {
13253                         emitCLRC;
13254                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13255
13256                         pic16_emitcode("clrc","");
13257                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13258                                 AOP(right)->aopu.aop_dir,
13259                                 AOP(right)->aopu.aop_dir);
13260                         pic16_aopPut(AOP(result),"c",0);
13261                         goto release ;
13262                 }
13263
13264                 /* we need to or */
13265                 if (AOP_TYPE(right) == AOP_REG) {
13266                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13267                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13268                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13269                 }
13270                 pic16_toBoolean(right);
13271                 pic16_aopPut(AOP(result),"a",0);
13272                 goto release ;
13273         }
13274
13275         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13276           int offset = 1;
13277
13278                 size = AOP_SIZE(result);
13279
13280                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13281
13282                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13283                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13284                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13285
13286                 while (size--)
13287                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13288
13289                 goto release;
13290         }
13291
13292         if(IS_BITFIELD(getSpec(restype))
13293           && IS_BITFIELD(getSpec(rtype))) {
13294           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13295         }
13296
13297         /* if they are the same size : or less */
13298         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13299
13300                 /* if they are in the same place */
13301                 if (pic16_sameRegs(AOP(right),AOP(result)))
13302                         goto release;
13303
13304                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13305 #if 0
13306                 if (IS_PTR_CONST(rtype))
13307 #else
13308                 if (IS_CODEPTR(rtype))
13309 #endif
13310                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13311
13312 #if 0
13313                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13314 #else
13315                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13316 #endif
13317                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13318
13319 #if 0
13320                 if(AOP_TYPE(right) == AOP_IMMD) {
13321                   pCodeOp *pcop0, *pcop1, *pcop2;
13322                   symbol *sym = OP_SYMBOL( right );
13323
13324                         size = AOP_SIZE(result);
13325                         /* low */
13326                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13327                         /* high */
13328                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13329                         /* upper */
13330                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13331         
13332                         if (size == 3) {
13333                                 pic16_emitpcode(POC_MOVLW, pcop0);
13334                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13335                                 pic16_emitpcode(POC_MOVLW, pcop1);
13336                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13337                                 pic16_emitpcode(POC_MOVLW, pcop2);
13338                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13339                         } else
13340                         if (size == 2) {
13341                                 pic16_emitpcode(POC_MOVLW, pcop0);
13342                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13343                                 pic16_emitpcode(POC_MOVLW, pcop1);
13344                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13345                         } else {
13346                                 pic16_emitpcode(POC_MOVLW, pcop0);
13347                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13348                         }
13349                 } else
13350 #endif
13351                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13352                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13353                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13354                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13355                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13356                         if(AOP_SIZE(result) <2)
13357                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13358                 } else {
13359                         /* if they in different places then copy */
13360                         size = AOP_SIZE(result);
13361                         offset = 0 ;
13362                         while (size--) {
13363                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13364                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13365                                 offset++;
13366                         }
13367                 }
13368                 goto release;
13369         }
13370
13371         /* if the result is of type pointer */
13372         if (IS_PTR(ctype)) {
13373           int p_type;
13374           sym_link *type = operandType(right);
13375           sym_link *etype = getSpec(type);
13376
13377                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13378
13379                 /* pointer to generic pointer */
13380                 if (IS_GENPTR(ctype)) {
13381                   char *l = zero;
13382             
13383                         if (IS_PTR(type)) 
13384                                 p_type = DCL_TYPE(type);
13385                         else {
13386                 /* we have to go by the storage class */
13387                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13388
13389 /*              if (SPEC_OCLS(etype)->codesp )  */
13390 /*                  p_type = CPOINTER ;  */
13391 /*              else */
13392 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13393 /*                      p_type = FPOINTER ; */
13394 /*                  else */
13395 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13396 /*                          p_type = PPOINTER; */
13397 /*                      else */
13398 /*                          if (SPEC_OCLS(etype) == idata ) */
13399 /*                              p_type = IPOINTER ; */
13400 /*                          else */
13401 /*                              p_type = POINTER ; */
13402             }
13403                 
13404             /* the first two bytes are known */
13405       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13406             size = GPTRSIZE - 1; 
13407             offset = 0 ;
13408             while (size--) {
13409               if(offset < AOP_SIZE(right)) {
13410                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13411                 mov2f(AOP(result), AOP(right), offset);
13412 /*
13413                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13414                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13415                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13416                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13417                 } else { 
13418                   
13419                   pic16_aopPut(AOP(result),
13420                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13421                          offset);
13422                 }
13423 */
13424               } else 
13425                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13426               offset++;
13427             }
13428             /* the last byte depending on type */
13429             switch (p_type) {
13430             case IPOINTER:
13431             case POINTER:
13432                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13433                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13434 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13435                 break;
13436
13437             case CPOINTER:
13438                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13439                 break;
13440
13441             case FPOINTER:
13442               pic16_emitcode(";BUG!? ","%d",__LINE__);
13443                 l = one;
13444                 break;
13445             case PPOINTER:
13446               pic16_emitcode(";BUG!? ","%d",__LINE__);
13447                 l = "#0x03";
13448                 break;
13449
13450             case GPOINTER:
13451                 if (GPTRSIZE > AOP_SIZE(right)) {
13452                   // assume data pointer... THIS MIGHT BE WRONG!
13453                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13454                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13455                 } else {
13456                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13457                 }
13458               break;
13459               
13460             default:
13461                 /* this should never happen */
13462                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13463                        "got unknown pointer type");
13464                 exit(1);
13465             }
13466             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13467             goto release ;
13468         }
13469         
13470         /* just copy the pointers */
13471         size = AOP_SIZE(result);
13472         offset = 0 ;
13473         while (size--) {
13474             pic16_aopPut(AOP(result),
13475                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13476                    offset);
13477             offset++;
13478         }
13479         goto release ;
13480     }
13481     
13482
13483
13484     /* so we now know that the size of destination is greater
13485     than the size of the source.
13486     Now, if the next iCode is an operator then we might be
13487     able to optimize the operation without performing a cast.
13488     */
13489     if(genMixedOperation(ic))
13490       goto release;
13491
13492     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13493     
13494     /* we move to result for the size of source */
13495     size = AOP_SIZE(right);
13496     offset = 0 ;
13497     while (size--) {
13498       mov2f(AOP(result), AOP(right), offset);
13499       offset++;
13500     }
13501
13502     /* now depending on the sign of the destination */
13503     size = AOP_SIZE(result) - AOP_SIZE(right);
13504     /* if unsigned or not an integral type */
13505     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13506       while (size--)
13507         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13508     } else {
13509       /* we need to extend the sign :( */
13510
13511       if(size == 1) {
13512         /* Save one instruction of casting char to int */
13513         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13514         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13515         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13516       } else {
13517         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13518
13519         if(offset)
13520           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13521         else
13522           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13523         
13524         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13525
13526         while (size--)
13527           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13528       }
13529     }
13530
13531 release:
13532     pic16_freeAsmop(right,NULL,ic,TRUE);
13533     pic16_freeAsmop(result,NULL,ic,TRUE);
13534
13535 }
13536
13537 /*-----------------------------------------------------------------*/
13538 /* genDjnz - generate decrement & jump if not zero instrucion      */
13539 /*-----------------------------------------------------------------*/
13540 static int genDjnz (iCode *ic, iCode *ifx)
13541 {
13542     symbol *lbl, *lbl1;
13543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13544
13545     if (!ifx)
13546         return 0;
13547     
13548     /* if the if condition has a false label
13549        then we cannot save */
13550     if (IC_FALSE(ifx))
13551         return 0;
13552
13553     /* if the minus is not of the form 
13554        a = a - 1 */
13555     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13556         !IS_OP_LITERAL(IC_RIGHT(ic)))
13557         return 0;
13558
13559     if (operandLitValue(IC_RIGHT(ic)) != 1)
13560         return 0;
13561
13562     /* if the size of this greater than one then no
13563        saving */
13564     if (getSize(operandType(IC_RESULT(ic))) > 1)
13565         return 0;
13566
13567     /* otherwise we can save BIG */
13568     lbl = newiTempLabel(NULL);
13569     lbl1= newiTempLabel(NULL);
13570
13571     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13572     
13573     if (IS_AOP_PREG(IC_RESULT(ic))) {
13574         pic16_emitcode("dec","%s",
13575                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13576         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13577         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13578     } else {    
13579
13580
13581       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13582       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13583
13584       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13585       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13586
13587     }
13588     
13589     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13590     ifx->generated = 1;
13591     return 1;
13592 }
13593
13594 /*-----------------------------------------------------------------*/
13595 /* genReceive - generate code for a receive iCode                  */
13596 /*-----------------------------------------------------------------*/
13597 static void genReceive (iCode *ic)
13598 {    
13599
13600   FENTRY;
13601
13602 #if 0
13603   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13604         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13605 #endif
13606 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13607
13608   if (isOperandInFarSpace(IC_RESULT(ic))
13609       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13610           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13611
13612     int size = getSize(operandType(IC_RESULT(ic)));
13613     int offset =  pic16_fReturnSizePic - size;
13614
13615       assert( 0 );
13616       while (size--) {
13617         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13618                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13619                       offset++;
13620         }
13621
13622       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13623
13624       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13625       size = AOP_SIZE(IC_RESULT(ic));
13626       offset = 0;
13627       while (size--) {
13628         pic16_emitcode ("pop","acc");
13629         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13630       }
13631   } else {
13632     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13633     _G.accInUse++;
13634     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13635     _G.accInUse--;
13636
13637     /* set pseudo stack pointer to where it should be - dw*/
13638     GpsuedoStkPtr = ic->parmBytes;
13639
13640     /* setting GpsuedoStkPtr has side effects here: */
13641     assignResultValue(IC_RESULT(ic), 0);
13642   }
13643
13644   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13645 }
13646
13647 /*-----------------------------------------------------------------*/
13648 /* genDummyRead - generate code for dummy read of volatiles        */
13649 /*-----------------------------------------------------------------*/
13650 static void
13651 genDummyRead (iCode * ic)
13652 {
13653   operand *op;
13654   int i;
13655
13656   op = IC_RIGHT(ic);
13657   if (op && IS_SYMOP(op)) {
13658     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13659       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13660       return;
13661     }
13662     pic16_aopOp (op, ic, FALSE);
13663     for (i=0; i < AOP_SIZE(op); i++) {
13664       // may need to protect this from the peepholer -- this is not nice but works...
13665       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13666       pic16_mov2w (AOP(op),i);
13667       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13668     } // for i
13669     pic16_freeAsmop (op, NULL, ic, TRUE);
13670   } else if (op) {
13671     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13672   } // if
13673 }
13674
13675 /*-----------------------------------------------------------------*/
13676 /* genpic16Code - generate code for pic16 based controllers        */
13677 /*-----------------------------------------------------------------*/
13678 /*
13679  * At this point, ralloc.c has gone through the iCode and attempted
13680  * to optimize in a way suitable for a PIC. Now we've got to generate
13681  * PIC instructions that correspond to the iCode.
13682  *
13683  * Once the instructions are generated, we'll pass through both the
13684  * peep hole optimizer and the pCode optimizer.
13685  *-----------------------------------------------------------------*/
13686
13687 void genpic16Code (iCode *lic)
13688 {
13689   iCode *ic;
13690   int cln = 0;
13691
13692     lineHead = lineCurr = NULL;
13693
13694     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13695     pic16_addpBlock(pb);
13696
13697 #if 0
13698     /* if debug information required */
13699     if (options.debug && currFunc) {
13700       if (currFunc) {
13701         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13702       }
13703     }
13704 #endif
13705
13706     for (ic = lic ; ic ; ic = ic->next ) {
13707
13708       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13709       if ( cln != ic->lineno ) {
13710         if ( options.debug ) {
13711           debugFile->writeCLine (ic);
13712         }
13713         
13714         if(!options.noCcodeInAsm) {
13715           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13716               printCLine(ic->filename, ic->lineno)));
13717         }
13718
13719         cln = ic->lineno ;
13720       }
13721         
13722       if(options.iCodeInAsm) {
13723         char *l;
13724
13725           /* insert here code to print iCode as comment */
13726           l = Safe_strdup(printILine(ic));
13727           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13728       }
13729         
13730       /* if the result is marked as
13731        * spilt and rematerializable or code for
13732        * this has already been generated then
13733        * do nothing */
13734       if (resultRemat(ic) || ic->generated ) 
13735         continue ;
13736         
13737       /* depending on the operation */
13738       switch (ic->op) {
13739         case '!' :
13740           pic16_genNot(ic);
13741           break;
13742             
13743         case '~' :
13744           pic16_genCpl(ic);
13745           break;
13746             
13747         case UNARYMINUS:
13748           genUminus (ic);
13749           break;
13750             
13751         case IPUSH:
13752           genIpush (ic);
13753           break;
13754             
13755         case IPOP:
13756           /* IPOP happens only when trying to restore a 
13757            * spilt live range, if there is an ifx statement
13758            * following this pop then the if statement might
13759            * be using some of the registers being popped which
13760            * would destroy the contents of the register so
13761            * we need to check for this condition and handle it */
13762            if (ic->next
13763              && ic->next->op == IFX
13764              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13765                genIfx (ic->next,ic);
13766           else
13767             genIpop (ic);
13768           break; 
13769             
13770         case CALL:
13771           genCall (ic);
13772           break;
13773             
13774         case PCALL:
13775           genPcall (ic);
13776           break;
13777             
13778         case FUNCTION:
13779           genFunction (ic);
13780           break;
13781             
13782         case ENDFUNCTION:
13783           genEndFunction (ic);
13784           break;
13785             
13786         case RETURN:
13787           genRet (ic);
13788           break;
13789             
13790         case LABEL:
13791           genLabel (ic);
13792           break;
13793             
13794         case GOTO:
13795           genGoto (ic);
13796           break;
13797             
13798         case '+' :
13799           pic16_genPlus (ic) ;
13800           break;
13801             
13802         case '-' :
13803           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13804             pic16_genMinus (ic);
13805           break;
13806
13807         case '*' :
13808           genMult (ic);
13809           break;
13810             
13811         case '/' :
13812           genDiv (ic) ;
13813           break;
13814             
13815         case '%' :
13816           genMod (ic);
13817           break;
13818             
13819         case '>' :
13820           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13821           break;
13822             
13823         case '<' :
13824           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13825           break;
13826             
13827         case LE_OP:
13828         case GE_OP:
13829         case NE_OP:
13830           /* note these two are xlated by algebraic equivalence
13831            * during parsing SDCC.y */
13832           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13833             "got '>=' or '<=' shouldn't have come here");
13834           break;
13835
13836         case EQ_OP:
13837           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13838           break;            
13839             
13840         case AND_OP:
13841           genAndOp (ic);
13842           break;
13843             
13844         case OR_OP:
13845           genOrOp (ic);
13846           break;
13847             
13848         case '^' :
13849           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13850           break;
13851             
13852         case '|' :
13853           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13854           break;
13855             
13856         case BITWISEAND:
13857           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13858           break;
13859             
13860         case INLINEASM:
13861           genInline (ic);
13862           break;
13863             
13864         case RRC:
13865           genRRC (ic);
13866           break;
13867             
13868         case RLC:
13869           genRLC (ic);
13870           break;
13871             
13872         case GETHBIT:
13873           genGetHbit (ic);
13874           break;
13875             
13876         case LEFT_OP:
13877           genLeftShift (ic);
13878           break;
13879             
13880         case RIGHT_OP:
13881           genRightShift (ic);
13882           break;
13883             
13884         case GET_VALUE_AT_ADDRESS:
13885           genPointerGet(ic);
13886           break;
13887             
13888         case '=' :
13889           if (POINTER_SET(ic))
13890             genPointerSet(ic);
13891           else
13892             genAssign(ic);
13893           break;
13894             
13895         case IFX:
13896           genIfx (ic,NULL);
13897           break;
13898             
13899         case ADDRESS_OF:
13900           genAddrOf (ic);
13901           break;
13902             
13903         case JUMPTABLE:
13904           genJumpTab (ic);
13905           break;
13906             
13907         case CAST:
13908           genCast (ic);
13909           break;
13910             
13911         case RECEIVE:
13912           genReceive(ic);
13913           break;
13914             
13915         case SEND:
13916           addSet(&_G.sendSet,ic);
13917           break;
13918
13919         case DUMMY_READ_VOLATILE:
13920           genDummyRead (ic);
13921           break;
13922
13923         default :
13924           ic = ic;
13925       }
13926     }
13927
13928
13929     /* now we are ready to call the
13930        peep hole optimizer */
13931     if (!options.nopeep)
13932       peepHole (&lineHead);
13933
13934     /* now do the actual printing */
13935     printLine (lineHead, codeOutFile);
13936
13937 #ifdef PCODE_DEBUG
13938     DFPRINTF((stderr,"printing pBlock\n\n"));
13939     pic16_printpBlock(stdout,pb);
13940 #endif
13941
13942     return;
13943 }
13944