d87d6303c7e0537e4f4aa108fc35e70dfe2cccc6
[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     while(res_size--)
10397       movLeft2Result(left, lsize, result, res_size);
10398   }
10399
10400   else if(shCount >= (lsize * 8)){
10401
10402     if(res_size == 1) {
10403       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10404       if(sign) {
10405         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10406         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10407       }
10408     } else {
10409
10410       if(sign) {
10411         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10412         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10413         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10414         while(res_size--)
10415           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10416
10417       } else {
10418
10419         while(res_size--)
10420           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10421       }
10422     }
10423   } else {
10424
10425     switch (res_size) {
10426     case 1:
10427       genrshOne (result,left,shCount,sign);
10428       break;
10429
10430     case 2:
10431       genrshTwo (result,left,shCount,sign);
10432       break;
10433
10434     case 4:
10435       genrshFour (result,left,shCount,sign);
10436       break;
10437     default :
10438       break;
10439     }
10440
10441   }
10442
10443   pic16_freeAsmop(left,NULL,ic,TRUE);
10444   pic16_freeAsmop(result,NULL,ic,TRUE);
10445 }
10446
10447 #if !(USE_GENERIC_SIGNED_SHIFT)
10448 /*-----------------------------------------------------------------*/
10449 /* genSignedRightShift - right shift of signed number              */
10450 /*-----------------------------------------------------------------*/
10451 static void genSignedRightShift (iCode *ic)
10452 {
10453   operand *right, *left, *result;
10454   int size, offset;
10455   //  char *l;
10456   symbol *tlbl, *tlbl1 ;
10457   pCodeOp *pctemp;
10458
10459   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10460
10461   /* we do it the hard way put the shift count in b
10462      and loop thru preserving the sign */
10463   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10464
10465   right = IC_RIGHT(ic);
10466   left  = IC_LEFT(ic);
10467   result = IC_RESULT(ic);
10468
10469   pic16_aopOp(right,ic,FALSE);  
10470   pic16_aopOp(left,ic,FALSE);
10471   pic16_aopOp(result,ic,FALSE);
10472
10473
10474   if ( AOP_TYPE(right) == AOP_LIT) {
10475     genRightShiftLiteral (left,right,result,ic,1);
10476     return ;
10477   }
10478   /* shift count is unknown then we have to form 
10479      a loop get the loop count in B : Note: we take
10480      only the lower order byte since shifting
10481      more that 32 bits make no sense anyway, ( the
10482      largest size of an object can be only 32 bits ) */  
10483
10484   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10485   //pic16_emitcode("inc","b");
10486   //pic16_freeAsmop (right,NULL,ic,TRUE);
10487   //pic16_aopOp(left,ic,FALSE);
10488   //pic16_aopOp(result,ic,FALSE);
10489
10490   /* now move the left to the result if they are not the
10491      same */
10492   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10493       AOP_SIZE(result) > 1) {
10494
10495     size = AOP_SIZE(result);
10496     offset=0;
10497     while (size--) { 
10498       /*
10499         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10500         if (*l == '@' && IS_AOP_PREG(result)) {
10501
10502         pic16_emitcode("mov","a,%s",l);
10503         pic16_aopPut(AOP(result),"a",offset);
10504         } else
10505         pic16_aopPut(AOP(result),l,offset);
10506       */
10507       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10508       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10509
10510       offset++;
10511     }
10512   }
10513
10514   /* mov the highest order bit to OVR */    
10515   tlbl = newiTempLabel(NULL);
10516   tlbl1= newiTempLabel(NULL);
10517
10518   size = AOP_SIZE(result);
10519   offset = size - 1;
10520
10521   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10522
10523   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10524
10525   /* offset should be 0, 1 or 3 */
10526   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10527   emitSKPNZ;
10528   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10529
10530   pic16_emitpcode(POC_MOVWF, pctemp);
10531
10532
10533   pic16_emitpLabel(tlbl->key);
10534
10535   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10536   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10537
10538   while(--size) {
10539     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10540   }
10541
10542   pic16_emitpcode(POC_DECFSZ,  pctemp);
10543   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10544   pic16_emitpLabel(tlbl1->key);
10545
10546   pic16_popReleaseTempReg(pctemp,1);
10547 #if 0
10548   size = AOP_SIZE(result);
10549   offset = size - 1;
10550   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10551   pic16_emitcode("rlc","a");
10552   pic16_emitcode("mov","ov,c");
10553   /* if it is only one byte then */
10554   if (size == 1) {
10555     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10556     MOVA(l);
10557     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10558     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10559     pic16_emitcode("mov","c,ov");
10560     pic16_emitcode("rrc","a");
10561     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10562     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10563     pic16_aopPut(AOP(result),"a",0);
10564     goto release ;
10565   }
10566
10567   reAdjustPreg(AOP(result));
10568   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10569   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10570   pic16_emitcode("mov","c,ov");
10571   while (size--) {
10572     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10573     MOVA(l);
10574     pic16_emitcode("rrc","a");         
10575     pic16_aopPut(AOP(result),"a",offset--);
10576   }
10577   reAdjustPreg(AOP(result));
10578   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10579   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10580
10581  release:
10582 #endif
10583
10584   pic16_freeAsmop(left,NULL,ic,TRUE);
10585   pic16_freeAsmop(result,NULL,ic,TRUE);
10586   pic16_freeAsmop(right,NULL,ic,TRUE);
10587 }
10588 #endif
10589
10590 #if !(USE_GENERIC_SIGNED_SHIFT)
10591 #warning This implementation of genRightShift() is incomplete!
10592 /*-----------------------------------------------------------------*/
10593 /* genRightShift - generate code for right shifting                */
10594 /*-----------------------------------------------------------------*/
10595 static void genRightShift (iCode *ic)
10596 {
10597     operand *right, *left, *result;
10598     sym_link *letype ;
10599     int size, offset;
10600     char *l;
10601     symbol *tlbl, *tlbl1 ;
10602
10603     /* if signed then we do it the hard way preserve the
10604     sign bit moving it inwards */
10605     letype = getSpec(operandType(IC_LEFT(ic)));
10606     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10607
10608     if (!SPEC_USIGN(letype)) {
10609         genSignedRightShift (ic);
10610         return ;
10611     }
10612
10613     /* signed & unsigned types are treated the same : i.e. the
10614     signed is NOT propagated inwards : quoting from the
10615     ANSI - standard : "for E1 >> E2, is equivalent to division
10616     by 2**E2 if unsigned or if it has a non-negative value,
10617     otherwise the result is implementation defined ", MY definition
10618     is that the sign does not get propagated */
10619
10620     right = IC_RIGHT(ic);
10621     left  = IC_LEFT(ic);
10622     result = IC_RESULT(ic);
10623
10624     pic16_aopOp(right,ic,FALSE);
10625
10626     /* if the shift count is known then do it 
10627     as efficiently as possible */
10628     if (AOP_TYPE(right) == AOP_LIT) {
10629         genRightShiftLiteral (left,right,result,ic, 0);
10630         return ;
10631     }
10632
10633     /* shift count is unknown then we have to form 
10634     a loop get the loop count in B : Note: we take
10635     only the lower order byte since shifting
10636     more that 32 bits make no sense anyway, ( the
10637     largest size of an object can be only 32 bits ) */  
10638
10639     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10640     pic16_emitcode("inc","b");
10641     pic16_aopOp(left,ic,FALSE);
10642     pic16_aopOp(result,ic,FALSE);
10643
10644     /* now move the left to the result if they are not the
10645     same */
10646     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10647         AOP_SIZE(result) > 1) {
10648
10649         size = AOP_SIZE(result);
10650         offset=0;
10651         while (size--) {
10652             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10653             if (*l == '@' && IS_AOP_PREG(result)) {
10654
10655                 pic16_emitcode("mov","a,%s",l);
10656                 pic16_aopPut(AOP(result),"a",offset);
10657             } else
10658                 pic16_aopPut(AOP(result),l,offset);
10659             offset++;
10660         }
10661     }
10662
10663     tlbl = newiTempLabel(NULL);
10664     tlbl1= newiTempLabel(NULL);
10665     size = AOP_SIZE(result);
10666     offset = size - 1;
10667
10668     /* if it is only one byte then */
10669     if (size == 1) {
10670
10671       tlbl = newiTempLabel(NULL);
10672       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10673         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10674         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10675       }
10676
10677       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10678       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10679       pic16_emitpLabel(tlbl->key);
10680       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10681       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10682       emitSKPC;
10683       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10684
10685       goto release ;
10686     }
10687
10688     reAdjustPreg(AOP(result));
10689     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10690     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10691     CLRC;
10692     while (size--) {
10693         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10694         MOVA(l);
10695         pic16_emitcode("rrc","a");         
10696         pic16_aopPut(AOP(result),"a",offset--);
10697     }
10698     reAdjustPreg(AOP(result));
10699
10700     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10701     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10702
10703 release:
10704     pic16_freeAsmop(left,NULL,ic,TRUE);
10705     pic16_freeAsmop (right,NULL,ic,TRUE);
10706     pic16_freeAsmop(result,NULL,ic,TRUE);
10707 }
10708 #endif
10709
10710 #if (USE_GENERIC_SIGNED_SHIFT)
10711 /*-----------------------------------------------------------------*/
10712 /* genGenericShift - generates code for left or right shifting     */
10713 /*-----------------------------------------------------------------*/
10714 static void genGenericShift (iCode *ic, int isShiftLeft) {
10715   operand *left,*right, *result;
10716   int offset;
10717   int sign, signedCount;
10718   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10719   PIC_OPCODE pos_shift, neg_shift;
10720
10721   FENTRY;
10722
10723   right = IC_RIGHT(ic);
10724   left  = IC_LEFT(ic);
10725   result = IC_RESULT(ic);
10726
10727   pic16_aopOp(right,ic,FALSE);
10728   pic16_aopOp(left,ic,FALSE);
10729   pic16_aopOp(result,ic,TRUE);
10730
10731   sign = !SPEC_USIGN(operandType (left));
10732   signedCount = !SPEC_USIGN(operandType (right));
10733
10734   /* if the shift count is known then do it 
10735      as efficiently as possible */
10736   if (AOP_TYPE(right) == AOP_LIT) {
10737     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10738     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10739     // we should modify right->aopu.aop_lit here!
10740     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10741     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10742     if (isShiftLeft)
10743       pic16_genLeftShiftLiteral (left,right,result,ic);
10744     else
10745       genRightShiftLiteral (left,right,result,ic, sign);
10746
10747     goto release;
10748   } // if (right is literal)
10749
10750   /* shift count is unknown then we have to form a loop.
10751    * Note: we take only the lower order byte since shifting
10752    * more than 32 bits make no sense anyway, ( the
10753    * largest size of an object can be only 32 bits )
10754    * Note: we perform arithmetic shifts if the left operand is
10755    * signed and we do an (effective) right shift, i. e. we
10756    * shift in the sign bit from the left. */
10757    
10758   label_complete = newiTempLabel ( NULL );
10759   label_loop_pos = newiTempLabel ( NULL );
10760   label_loop_neg = NULL;
10761   label_negative = NULL;
10762   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10763   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10764
10765   if (signedCount) {
10766     // additional labels needed
10767     label_loop_neg = newiTempLabel ( NULL );
10768     label_negative = newiTempLabel ( NULL );
10769   } // if
10770
10771   // copy source to result -- this will effectively truncate the left operand to the size of result!
10772   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10773   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10774   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10775     mov2f (AOP(result),AOP(left), offset);
10776   } // for
10777
10778   // if result is longer than left, fill with zeros (or sign)
10779   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10780     if (sign && AOP_SIZE(left) > 0) {
10781       // shift signed operand -- fill with sign
10782       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10783       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10784       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10785       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10786         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10787       } // for
10788     } else {
10789       // shift unsigned operand -- fill result with zeros
10790       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10791         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10792       } // for
10793     }
10794   } // if (size mismatch)
10795
10796   pic16_mov2w (AOP(right), 0);
10797   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10798   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10799   
10800 #if 0
10801   // perform a shift by one (shift count is positive)
10802   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10803   // 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])
10804   pic16_emitpLabel (label_loop_pos->key);
10805   emitCLRC;
10806   if (sign && (pos_shift == POC_RRCF)) {
10807     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10808     emitSETC;
10809   } // if
10810   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10811   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10812   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10813 #else
10814   // perform a shift by one (shift count is positive)
10815   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10816   // 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])
10817   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10818   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10819   emitCLRC;
10820   pic16_emitpLabel (label_loop_pos->key);
10821   if (sign && (pos_shift == POC_RRCF)) {
10822     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10823     emitSETC;
10824   } // if
10825   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10826   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10827   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10828   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10829 #endif
10830
10831   if (signedCount) {
10832     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10833
10834     pic16_emitpLabel (label_negative->key);
10835     // perform a shift by -1 (shift count is negative)
10836     // 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)
10837     emitCLRC;
10838     pic16_emitpLabel (label_loop_neg->key);
10839     if (sign && (neg_shift == POC_RRCF)) {
10840       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10841       emitSETC;
10842     } // if
10843     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10844     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10845     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10846     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10847   } // if (signedCount)
10848
10849   pic16_emitpLabel (label_complete->key);
10850
10851 release:
10852   pic16_freeAsmop (right,NULL,ic,TRUE);
10853   pic16_freeAsmop(left,NULL,ic,TRUE);
10854   pic16_freeAsmop(result,NULL,ic,TRUE);
10855 }
10856
10857 static void genLeftShift (iCode *ic) {
10858   genGenericShift (ic, 1);
10859 }
10860
10861 static void genRightShift (iCode *ic) {
10862   genGenericShift (ic, 0);
10863 }
10864 #endif
10865
10866
10867 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10868 void pic16_loadFSR0(operand *op, int lit)
10869 {
10870   if(is_LitOp( op ) || lit) {
10871     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10872   } else {
10873     // set up FSR0 with address of result
10874     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10875     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10876   }
10877 }
10878
10879 /*-----------------------------------------------------------------*/
10880 /* genUnpackBits - generates code for unpacking bits               */
10881 /*-----------------------------------------------------------------*/
10882 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10883 {    
10884   int shCnt ;
10885   int rlen = 0 ;
10886   sym_link *etype, *letype;
10887   int blen=0, bstr=0;
10888   int lbstr;
10889   int offset = 0 ;
10890
10891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10892     etype = getSpec(operandType(result));
10893     letype = getSpec(operandType(left));
10894     
10895 //    if(IS_BITFIELD(etype)) {
10896       blen = SPEC_BLEN(etype);
10897       bstr = SPEC_BSTR(etype);
10898 //    }
10899
10900     lbstr = SPEC_BSTR( letype );
10901
10902 #if 1
10903     if((blen == 1) && (bstr < 8)) {
10904       /* it is a single bit, so use the appropriate bit instructions */
10905       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10906
10907       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10908       
10909       if((ptype == POINTER) && (result)) {
10910         /* workaround to reduce the extra lfsr instruction */
10911         pic16_emitpcode(POC_BTFSC,
10912               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10913       } else {
10914         pic16_emitpcode(POC_BTFSC,
10915               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10916       }
10917         
10918       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10919
10920       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10921       return;
10922     }
10923
10924 #endif
10925
10926         /* the following call to pic16_loadFSR0 is temporary until
10927          * optimization to handle single bit assignments is added
10928          * to the function. Until then use the old safe way! -- VR */
10929         pic16_loadFSR0( left, 1 );
10930  
10931         /* read the first byte  */
10932         switch (ptype) {
10933                 case POINTER:
10934                 case IPOINTER:
10935                 case PPOINTER:
10936                 case FPOINTER:
10937                 case GPOINTER:
10938                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10939                         break;
10940                 case CPOINTER:
10941                         pic16_emitcode("clr","a");
10942                         pic16_emitcode("movc","a","@a+dptr");
10943                         break;
10944         }
10945         
10946
10947         /* if we have bitdisplacement then it fits   */
10948         /* into this byte completely or if length is */
10949         /* less than a byte                          */
10950         if ((shCnt = SPEC_BSTR(etype)) || 
10951                 (SPEC_BLEN(etype) <= 8))  {
10952
10953                 /* shift right acc */
10954                 AccRsh(shCnt, 0);
10955
10956                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10957                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10958
10959 /* VR -- normally I would use the following, but since we use the hack,
10960  * to avoid the masking from AccRsh, why not mask it right now? */
10961
10962 /*
10963                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10964 */
10965
10966                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10967           return ;
10968         }
10969
10970
10971
10972         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10973         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10974         exit(-1);
10975
10976     /* bit field did not fit in a byte  */
10977     rlen = SPEC_BLEN(etype) - 8;
10978     pic16_aopPut(AOP(result),"a",offset++);
10979
10980     while (1)  {
10981
10982         switch (ptype) {
10983         case POINTER:
10984         case IPOINTER:
10985             pic16_emitcode("inc","%s",rname);
10986             pic16_emitcode("mov","a,@%s",rname);
10987             break;
10988             
10989         case PPOINTER:
10990             pic16_emitcode("inc","%s",rname);
10991             pic16_emitcode("movx","a,@%s",rname);
10992             break;
10993
10994         case FPOINTER:
10995             pic16_emitcode("inc","dptr");
10996             pic16_emitcode("movx","a,@dptr");
10997             break;
10998             
10999         case CPOINTER:
11000             pic16_emitcode("clr","a");
11001             pic16_emitcode("inc","dptr");
11002             pic16_emitcode("movc","a","@a+dptr");
11003             break;
11004             
11005         case GPOINTER:
11006             pic16_emitcode("inc","dptr");
11007             pic16_emitcode("lcall","__gptrget");
11008             break;
11009         }
11010
11011         rlen -= 8;            
11012         /* if we are done */
11013         if ( rlen <= 0 )
11014             break ;
11015         
11016         pic16_aopPut(AOP(result),"a",offset++);
11017                               
11018     }
11019     
11020     if (rlen) {
11021         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11022         pic16_aopPut(AOP(result),"a",offset);          
11023     }
11024     
11025     return ;
11026 }
11027
11028
11029 static void genDataPointerGet(operand *left,
11030                               operand *result,
11031                               iCode *ic)
11032 {
11033   int size, offset = 0, leoffset=0 ;
11034
11035         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11036         pic16_aopOp(result, ic, TRUE);
11037
11038         size = AOP_SIZE(result);
11039 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11040
11041
11042 #if 0
11043         /* The following tests may save a redudant movff instruction when
11044          * accessing unions */
11045          
11046         /* if they are the same */
11047         if (operandsEqu (left, result)) {
11048                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11049                 goto release;
11050         }
11051 #endif
11052
11053 #if 0
11054         /* if they are the same registers */
11055         if (pic16_sameRegs(AOP(left),AOP(result))) {
11056                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11057                 goto release;
11058         }
11059 #endif
11060
11061 #if 1
11062         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11063                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11064                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11065                 goto release;
11066         }
11067 #endif
11068
11069
11070 #if 0
11071         if ( AOP_TYPE(left) == AOP_PCODE) {
11072                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11073                                 AOP(left)->aopu.pcop->name,
11074                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11075                                 PCOR(AOP(left)->aopu.pcop)->instance:
11076                                 PCOI(AOP(left)->aopu.pcop)->offset);
11077         }
11078 #endif
11079
11080         if(AOP(left)->aopu.pcop->type == PO_DIR)
11081                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11082
11083         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11084
11085         while (size--) {
11086                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11087                 
11088                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11089                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11090                         pic16_mov2w(AOP(left), offset); // patch 8
11091                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11092                 } else {
11093                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11094                                 pic16_popGet(AOP(left), offset), //patch 8
11095                                 pic16_popGet(AOP(result), offset)));
11096                 }
11097
11098                 offset++;
11099                 leoffset++;
11100         }
11101
11102 release:
11103     pic16_freeAsmop(result,NULL,ic,TRUE);
11104 }
11105
11106
11107
11108 /*-----------------------------------------------------------------*/
11109 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11110 /*-----------------------------------------------------------------*/
11111 static void genNearPointerGet (operand *left, 
11112                                operand *result, 
11113                                iCode *ic)
11114 {
11115 //  asmop *aop = NULL;
11116   //regs *preg = NULL ;
11117   sym_link *rtype, *retype;
11118   sym_link *ltype = operandType(left);    
11119
11120     FENTRY;
11121     
11122     rtype = operandType(result);
11123     retype= getSpec(rtype);
11124     
11125     pic16_aopOp(left,ic,FALSE);
11126
11127 //    pic16_DumpOp("(left)",left);
11128 //    pic16_DumpOp("(result)",result);
11129
11130     /* if left is rematerialisable and
11131      * result is not bit variable type and
11132      * the left is pointer to data space i.e
11133      * lower 128 bytes of space */
11134     
11135     if (AOP_TYPE(left) == AOP_PCODE
11136       && !IS_BITFIELD(retype)
11137       && DCL_TYPE(ltype) == POINTER) {
11138
11139         genDataPointerGet (left,result,ic);
11140         pic16_freeAsmop(left, NULL, ic, TRUE);
11141         return ;
11142     }
11143     
11144     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11145     pic16_aopOp (result,ic,TRUE);
11146     
11147     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11148
11149 #if 1
11150     if(IS_BITFIELD( retype )
11151       && (SPEC_BLEN(operandType(result))==1)
11152     ) {
11153       iCode *nextic;
11154       pCodeOp *jop;
11155       int bitstrt, bytestrt;
11156
11157         /* if this is bitfield of size 1, see if we are checking the value
11158          * of a single bit in an if-statement,
11159          * if yes, then don't generate usual code, but execute the
11160          * genIfx directly -- VR */
11161
11162         nextic = ic->next;
11163
11164         /* CHECK: if next iCode is IFX
11165          * and current result operand is nextic's conditional operand
11166          * and current result operand live ranges ends at nextic's key number
11167          */
11168         if((nextic->op == IFX)
11169           && (result == IC_COND(nextic))
11170           && (OP_LIVETO(result) == nextic->seq)
11171           ) {
11172             /* everything is ok then */
11173             /* find a way to optimize the genIfx iCode */
11174
11175             bytestrt = SPEC_BSTR(operandType(result))/8;
11176             bitstrt = SPEC_BSTR(operandType(result))%8;
11177             
11178             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11179
11180             genIfxpCOpJump(nextic, jop);
11181             
11182             pic16_freeAsmop(left, NULL, ic, TRUE);
11183             pic16_freeAsmop(result, NULL, ic, TRUE);
11184             return;
11185         }
11186     }
11187 #endif
11188
11189
11190     /* if the value is already in a pointer register
11191      * then don't need anything more */
11192     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11193       /* otherwise get a free pointer register */
11194       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11195                 
11196       ;
11197     }
11198
11199     /* if bitfield then unpack the bits */
11200     if (IS_BITFIELD(retype)) 
11201       genUnpackBits (result, left, NULL, POINTER);
11202     else {
11203       /* we have can just get the values */
11204       int size = AOP_SIZE(result);
11205       int offset = 0;   
11206         
11207       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11208
11209       pic16_loadFSR0( left, 0 );
11210
11211       while(size--) {
11212         if(size) {
11213           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11214                 pic16_popGet(AOP(result), offset++)));
11215         } else {
11216           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11217                 pic16_popGet(AOP(result), offset++)));
11218         }
11219       }
11220     }
11221
11222 #if 0
11223     /* now some housekeeping stuff */
11224     if (aop) {
11225       /* we had to allocate for this iCode */
11226       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11227       pic16_freeAsmop(NULL,aop,ic,TRUE);
11228     } else { 
11229       /* we did not allocate which means left
11230        * already in a pointer register, then
11231        * if size > 0 && this could be used again
11232        * we have to point it back to where it 
11233        * belongs */
11234       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11235       if (AOP_SIZE(result) > 1
11236         && !OP_SYMBOL(left)->remat
11237         && ( OP_SYMBOL(left)->liveTo > ic->seq
11238             || ic->depth )) {
11239 //        int size = AOP_SIZE(result) - 1;
11240 //        while (size--)
11241 //          pic16_emitcode("dec","%s",rname);
11242         }
11243     }
11244 #endif
11245
11246     /* done */
11247     pic16_freeAsmop(left,NULL,ic,TRUE);
11248     pic16_freeAsmop(result,NULL,ic,TRUE);
11249 }
11250
11251 /*-----------------------------------------------------------------*/
11252 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11253 /*-----------------------------------------------------------------*/
11254 static void genPagedPointerGet (operand *left, 
11255                                operand *result, 
11256                                iCode *ic)
11257 {
11258     asmop *aop = NULL;
11259     regs *preg = NULL ;
11260     char *rname ;
11261     sym_link *rtype, *retype;    
11262
11263     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11264
11265     rtype = operandType(result);
11266     retype= getSpec(rtype);
11267     
11268     pic16_aopOp(left,ic,FALSE);
11269
11270   /* if the value is already in a pointer register
11271        then don't need anything more */
11272     if (!AOP_INPREG(AOP(left))) {
11273         /* otherwise get a free pointer register */
11274         aop = newAsmop(0);
11275         preg = getFreePtr(ic,&aop,FALSE);
11276         pic16_emitcode("mov","%s,%s",
11277                 preg->name,
11278                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11279         rname = preg->name ;
11280     } else
11281         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11282     
11283     pic16_freeAsmop(left,NULL,ic,TRUE);
11284     pic16_aopOp (result,ic,TRUE);
11285
11286     /* if bitfield then unpack the bits */
11287     if (IS_BITFIELD(retype)) 
11288         genUnpackBits (result,left,rname,PPOINTER);
11289     else {
11290         /* we have can just get the values */
11291         int size = AOP_SIZE(result);
11292         int offset = 0 ;        
11293         
11294         while (size--) {
11295             
11296             pic16_emitcode("movx","a,@%s",rname);
11297             pic16_aopPut(AOP(result),"a",offset);
11298             
11299             offset++ ;
11300             
11301             if (size)
11302                 pic16_emitcode("inc","%s",rname);
11303         }
11304     }
11305
11306     /* now some housekeeping stuff */
11307     if (aop) {
11308         /* we had to allocate for this iCode */
11309         pic16_freeAsmop(NULL,aop,ic,TRUE);
11310     } else { 
11311         /* we did not allocate which means left
11312            already in a pointer register, then
11313            if size > 0 && this could be used again
11314            we have to point it back to where it 
11315            belongs */
11316         if (AOP_SIZE(result) > 1 &&
11317             !OP_SYMBOL(left)->remat &&
11318             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11319               ic->depth )) {
11320             int size = AOP_SIZE(result) - 1;
11321             while (size--)
11322                 pic16_emitcode("dec","%s",rname);
11323         }
11324     }
11325
11326     /* done */
11327     pic16_freeAsmop(result,NULL,ic,TRUE);
11328     
11329         
11330 }
11331
11332 /*-----------------------------------------------------------------*/
11333 /* genFarPointerGet - gget value from far space                    */
11334 /*-----------------------------------------------------------------*/
11335 static void genFarPointerGet (operand *left,
11336                               operand *result, iCode *ic)
11337 {
11338     int size, offset ;
11339     sym_link *retype = getSpec(operandType(result));
11340
11341     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11342
11343     pic16_aopOp(left,ic,FALSE);
11344
11345     /* if the operand is already in dptr 
11346     then we do nothing else we move the value to dptr */
11347     if (AOP_TYPE(left) != AOP_STR) {
11348         /* if this is remateriazable */
11349         if (AOP_TYPE(left) == AOP_IMMD)
11350             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11351         else { /* we need to get it byte by byte */
11352             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11353             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11354             if (options.model == MODEL_FLAT24)
11355             {
11356                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11357             }
11358         }
11359     }
11360     /* so dptr know contains the address */
11361     pic16_freeAsmop(left,NULL,ic,TRUE);
11362     pic16_aopOp(result,ic,TRUE);
11363
11364     /* if bit then unpack */
11365     if (IS_BITFIELD(retype)) 
11366         genUnpackBits(result,left,"dptr",FPOINTER);
11367     else {
11368         size = AOP_SIZE(result);
11369         offset = 0 ;
11370
11371         while (size--) {
11372             pic16_emitcode("movx","a,@dptr");
11373             pic16_aopPut(AOP(result),"a",offset++);
11374             if (size)
11375                 pic16_emitcode("inc","dptr");
11376         }
11377     }
11378
11379     pic16_freeAsmop(result,NULL,ic,TRUE);
11380 }
11381
11382 #if 0
11383 /*-----------------------------------------------------------------*/
11384 /* genCodePointerGet - get value from code space                  */
11385 /*-----------------------------------------------------------------*/
11386 static void genCodePointerGet (operand *left,
11387                                 operand *result, iCode *ic)
11388 {
11389     int size, offset ;
11390     sym_link *retype = getSpec(operandType(result));
11391
11392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11393
11394     pic16_aopOp(left,ic,FALSE);
11395
11396     /* if the operand is already in dptr 
11397     then we do nothing else we move the value to dptr */
11398     if (AOP_TYPE(left) != AOP_STR) {
11399         /* if this is remateriazable */
11400         if (AOP_TYPE(left) == AOP_IMMD)
11401             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11402         else { /* we need to get it byte by byte */
11403             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11404             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11405             if (options.model == MODEL_FLAT24)
11406             {
11407                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11408             }
11409         }
11410     }
11411     /* so dptr know contains the address */
11412     pic16_freeAsmop(left,NULL,ic,TRUE);
11413     pic16_aopOp(result,ic,FALSE);
11414
11415     /* if bit then unpack */
11416     if (IS_BITFIELD(retype)) 
11417         genUnpackBits(result,left,"dptr",CPOINTER);
11418     else {
11419         size = AOP_SIZE(result);
11420         offset = 0 ;
11421
11422         while (size--) {
11423             pic16_emitcode("clr","a");
11424             pic16_emitcode("movc","a,@a+dptr");
11425             pic16_aopPut(AOP(result),"a",offset++);
11426             if (size)
11427                 pic16_emitcode("inc","dptr");
11428         }
11429     }
11430
11431     pic16_freeAsmop(result,NULL,ic,TRUE);
11432 }
11433 #endif
11434
11435 #if 0
11436 /*-----------------------------------------------------------------*/
11437 /* genGenPointerGet - gget value from generic pointer space        */
11438 /*-----------------------------------------------------------------*/
11439 static void genGenPointerGet (operand *left,
11440                               operand *result, iCode *ic)
11441 {
11442   int size, offset, lit;
11443   sym_link *retype = getSpec(operandType(result));
11444
11445         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11446         pic16_aopOp(left,ic,FALSE);
11447         pic16_aopOp(result,ic,FALSE);
11448         size = AOP_SIZE(result);
11449
11450         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11451
11452         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11453
11454                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11455                 // load FSR0 from immediate
11456                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11457
11458 //              pic16_loadFSR0( left );
11459
11460                 offset = 0;
11461                 while(size--) {
11462                         if(size) {
11463                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11464                         } else {
11465                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11466                         }
11467                         offset++;
11468                 }
11469                 goto release;
11470
11471         }
11472         else { /* we need to get it byte by byte */
11473                 // set up FSR0 with address from left
11474                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11475                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11476                 
11477                 offset = 0 ;
11478
11479                 while(size--) {
11480                         if(size) {
11481                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11482                         } else {
11483                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11484                         }
11485                         offset++;
11486                 }
11487                 goto release;
11488         }
11489
11490   /* if bit then unpack */
11491         if (IS_BITFIELD(retype)) 
11492                 genUnpackBits(result,left,"BAD",GPOINTER);
11493
11494         release:
11495         pic16_freeAsmop(left,NULL,ic,TRUE);
11496         pic16_freeAsmop(result,NULL,ic,TRUE);
11497
11498 }
11499 #endif
11500
11501
11502 /*-----------------------------------------------------------------*/
11503 /* genGenPointerGet - gget value from generic pointer space        */
11504 /*-----------------------------------------------------------------*/
11505 static void genGenPointerGet (operand *left,
11506                               operand *result, iCode *ic)
11507 {
11508   int size, offset, lit;
11509   sym_link *retype = getSpec(operandType(result));
11510   char fgptrget[32];
11511
11512     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11513     pic16_aopOp(left,ic,FALSE);
11514     pic16_aopOp(result,ic,TRUE);
11515     size = AOP_SIZE(result);
11516
11517     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11518
11519     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11520
11521       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11522       // load FSR0 from immediate
11523       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11524
11525       werror(W_POSSBUG2, __FILE__, __LINE__);
11526
11527       offset = 0;
11528       while(size--) {
11529         if(size) {
11530           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11531         } else {
11532           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11533         }
11534         offset++;
11535       }
11536
11537       goto release;
11538
11539     } else { /* we need to get it byte by byte */
11540
11541       /* set up WREG:PRODL:FSR0L with address from left */
11542       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11543       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11544       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11545       
11546       switch( size ) {
11547         case 1: strcpy(fgptrget, "__gptrget1"); break;
11548         case 2: strcpy(fgptrget, "__gptrget2"); break;
11549         case 3: strcpy(fgptrget, "__gptrget3"); break;
11550         case 4: strcpy(fgptrget, "__gptrget4"); break;
11551         default:
11552           werror(W_POSSBUG2, __FILE__, __LINE__);
11553           abort();
11554       }
11555       
11556       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11557       
11558       assignResultValue(result, 1);
11559       
11560       {
11561         symbol *sym;
11562
11563           sym = newSymbol( fgptrget, 0 );
11564           sym->used++;
11565           strcpy(sym->rname, fgptrget);
11566           checkAddSym(&externs, sym);
11567
11568 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11569       }
11570               
11571       goto release;
11572     }
11573
11574   /* if bit then unpack */
11575     if (IS_BITFIELD(retype)) 
11576       genUnpackBits(result,left,"BAD",GPOINTER);
11577
11578 release:
11579   pic16_freeAsmop(left,NULL,ic,TRUE);
11580   pic16_freeAsmop(result,NULL,ic,TRUE);
11581 }
11582
11583 /*-----------------------------------------------------------------*/
11584 /* genConstPointerGet - get value from const generic pointer space */
11585 /*-----------------------------------------------------------------*/
11586 static void genConstPointerGet (operand *left,
11587                                 operand *result, iCode *ic)
11588 {
11589   //sym_link *retype = getSpec(operandType(result));
11590   // symbol *albl = newiTempLabel(NULL);        // patch 15
11591   // symbol *blbl = newiTempLabel(NULL);        //
11592   // PIC_OPCODE poc;                            // patch 15
11593   int size;
11594   int offset = 0;
11595
11596   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11597   pic16_aopOp(left,ic,FALSE);
11598   pic16_aopOp(result,ic,TRUE);
11599   size = AOP_SIZE(result);
11600
11601   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11602
11603   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11604
11605   // set up table pointer
11606   if( (AOP_TYPE(left) == AOP_PCODE) 
11607       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11608           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11609     {
11610       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11611       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11612       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11613       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11614       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11615       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11616   } else {
11617     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11618     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11619     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11620   }
11621
11622   while(size--) {
11623     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11624     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11625     offset++;
11626   }
11627     
11628   pic16_freeAsmop(left,NULL,ic,TRUE);
11629   pic16_freeAsmop(result,NULL,ic,TRUE);
11630 }
11631
11632
11633 /*-----------------------------------------------------------------*/
11634 /* genPointerGet - generate code for pointer get                   */
11635 /*-----------------------------------------------------------------*/
11636 static void genPointerGet (iCode *ic)
11637 {
11638   operand *left, *result ;
11639   sym_link *type, *etype;
11640   int p_type;
11641
11642     FENTRY;
11643     
11644     left = IC_LEFT(ic);
11645     result = IC_RESULT(ic) ;
11646
11647     /* depending on the type of pointer we need to
11648     move it to the correct pointer register */
11649     type = operandType(left);
11650     etype = getSpec(type);
11651
11652 #if 0
11653     if (IS_PTR_CONST(type))
11654 #else
11655     if (IS_CODEPTR(type))
11656 #endif
11657       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11658
11659     /* if left is of type of pointer then it is simple */
11660     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11661       p_type = DCL_TYPE(type);
11662     else {
11663       /* we have to go by the storage class */
11664       p_type = PTR_TYPE(SPEC_OCLS(etype));
11665
11666       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11667
11668       if (SPEC_OCLS(etype)->codesp ) {
11669         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11670         //p_type = CPOINTER ;   
11671       } else
11672       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11673         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11674         /*p_type = FPOINTER ;*/ 
11675       } else
11676       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11677         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11678         /* p_type = PPOINTER; */
11679       } else
11680       if (SPEC_OCLS(etype) == idata ) {
11681         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11682         /* p_type = IPOINTER; */
11683       } else {
11684         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11685         /* p_type = POINTER ; */
11686       }
11687     }
11688
11689     /* now that we have the pointer type we assign
11690     the pointer values */
11691     switch (p_type) {
11692       case POINTER:     
11693       case IPOINTER:
11694         genNearPointerGet (left,result,ic);
11695         break;
11696
11697       case PPOINTER:
11698         genPagedPointerGet(left,result,ic);
11699         break;
11700
11701       case FPOINTER:
11702         genFarPointerGet (left,result,ic);
11703         break;
11704
11705       case CPOINTER:
11706         genConstPointerGet (left,result,ic);
11707         //pic16_emitcodePointerGet (left,result,ic);
11708         break;
11709
11710       case GPOINTER:
11711 #if 0
11712       if (IS_PTR_CONST(type))
11713         genConstPointerGet (left,result,ic);
11714       else
11715 #endif
11716         genGenPointerGet (left,result,ic);
11717       break;
11718
11719     default:
11720       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11721               "genPointerGet: illegal pointer type");
11722     
11723     }
11724 }
11725
11726 /*-----------------------------------------------------------------*/
11727 /* genPackBits - generates code for packed bit storage             */
11728 /*-----------------------------------------------------------------*/
11729 static void genPackBits (sym_link    *etype , operand *result,
11730                          operand *right ,
11731                          char *rname, int p_type)
11732 {
11733   int shCnt = 0 ;
11734   int offset = 0  ;
11735   int rLen = 0 ;
11736   int blen, bstr ;   
11737   sym_link *retype;
11738
11739         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11740         blen = SPEC_BLEN(etype);
11741         bstr = SPEC_BSTR(etype);
11742
11743         retype = getSpec(operandType(right));
11744
11745         if(AOP_TYPE(right) == AOP_LIT) {
11746                 if((blen == 1) && (bstr < 8)) {
11747                   unsigned long lit;
11748                         /* it is a single bit, so use the appropriate bit instructions */
11749
11750                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11751
11752                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11753 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11754                         if((p_type == POINTER) && (result)) {
11755                                 /* workaround to reduce the extra lfsr instruction */
11756                                 if(lit) {
11757                                         pic16_emitpcode(POC_BSF,
11758                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11759                                 } else {
11760                                         pic16_emitpcode(POC_BCF,
11761                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11762                                 }
11763                         } else {
11764                                 pic16_loadFSR0(result, 1);
11765                                 if(lit) {
11766                                         pic16_emitpcode(POC_BSF,
11767                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11768                                 } else {
11769                                         pic16_emitpcode(POC_BCF,
11770                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11771                                 }
11772                         }
11773         
11774                   return;
11775                 }
11776                 /* move literal to W */
11777                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11778                 offset++;
11779         } else
11780         if(IS_BITFIELD(retype) 
11781           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11782           && (blen == 1)) {
11783           int rblen, rbstr;
11784
11785             rblen = SPEC_BLEN( retype );
11786             rbstr = SPEC_BSTR( retype );
11787             
11788
11789             if(IS_BITFIELD(etype)) {
11790               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11791               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11792             } else {
11793               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11794             }
11795             
11796             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11797             
11798             if(IS_BITFIELD(etype)) {
11799               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11800             } else {
11801               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11802             }
11803
11804             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11805             
11806             return;
11807         } else {
11808           /* move right to W */
11809           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11810         }
11811
11812         /* if the bit length is less than or   */
11813         /* it exactly fits a byte then         */
11814         if((shCnt=SPEC_BSTR(etype))
11815                 || SPEC_BLEN(etype) <= 8 )  {
11816                 int fsr0_setup = 0;
11817
11818                 if (blen != 8 || bstr != 0) {
11819                   // we need to combine the value with the old value
11820                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11821
11822           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11823                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11824                 
11825                   /* shift left acc */
11826                   AccLsh(shCnt);
11827
11828                   /* using PRODH as a temporary register here */
11829                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11830
11831                   /* get old value */
11832                   switch (p_type) {
11833                         case FPOINTER:
11834                         case POINTER:
11835                                 pic16_loadFSR0( result, 1 );
11836                                 fsr0_setup = 1;
11837                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11838 //                              pic16_emitcode ("mov","b,a");
11839 //                              pic16_emitcode("mov","a,@%s",rname);
11840                                 break;
11841
11842                         case GPOINTER:
11843                                 if (AOP(result)->aopu.aop_reg[2]) {
11844                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11845                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11846                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11847                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11848                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11849                                   {
11850                                     symbol *sym;
11851                                     sym = newSymbol( "__gptrget1", 0 );
11852                                     strcpy(sym->rname, "__gptrget1");
11853                                     checkAddSym(&externs, sym);
11854                                   }
11855                                 } else {
11856                                   // data pointer (just 2 byte given)
11857                                   pic16_loadFSR0( result, 1 );
11858                                   fsr0_setup = 1;
11859                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11860                                 }
11861                                 
11862                                 // warnings will be emitted below
11863                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11864                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11865                                 break;
11866
11867                         default:
11868                                 assert (0 && "invalid pointer type specified");
11869                                 break;
11870                   }
11871 #if 1
11872                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11873                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11874                                         (unsigned char)(0xff >> (8-bstr))) ));
11875                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11876                 } // if (blen != 8 || bstr != 0)
11877
11878                 /* write new value back */
11879                 switch (p_type) {
11880                         case FPOINTER:
11881                         case POINTER:
11882                                 if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11883                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11884                                 break;
11885
11886                         case GPOINTER:
11887                                 if (AOP(result)->aopu.aop_reg[2]) {
11888                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11889                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11890                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11891                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11892                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11893                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11894                                   {
11895                                     symbol *sym;
11896                                     sym = newSymbol( "__gptrput1", 0 );
11897                                     strcpy(sym->rname, "__gptrput1");
11898                                     checkAddSym(&externs, sym);
11899                                   }
11900                                 } else {
11901                                   // data pointer (just 2 byte given)
11902                                   if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11903                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11904                                 }
11905                                 
11906                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11907                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11908                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11909                                 break;
11910
11911                         default:
11912                                 assert (0 && "invalid pointer type specified");
11913                                 break;
11914                 }
11915 #endif
11916
11917           return;
11918         }
11919
11920
11921 #if 0
11922         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11923         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11924         exit(-1);
11925 #endif
11926
11927
11928     pic16_loadFSR0(result, 1);                  // load FSR0 with address of result
11929     rLen = SPEC_BLEN(etype)-8;
11930     
11931     /* now generate for lengths greater than one byte */
11932     while (1) {
11933         rLen -= 8 ;
11934         if (rLen <= 0 ) {
11935           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11936           break ;
11937         }
11938
11939         switch (p_type) {
11940             case POINTER:
11941                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11942                 break;
11943
11944 /*
11945             case FPOINTER:
11946                 MOVA(l);
11947                 pic16_emitcode("movx","@dptr,a");
11948                 break;
11949
11950             case GPOINTER:
11951                 MOVA(l);
11952                 DEBUGpic16_emitcode(";lcall","__gptrput");
11953                 break;  
11954 */
11955           default:
11956             assert(0);
11957         }   
11958
11959
11960         pic16_mov2w(AOP(right), offset++);
11961     }
11962
11963     /* last last was not complete */
11964     if (rLen)   {
11965         /* save the byte & read byte */
11966         switch (p_type) {
11967             case POINTER:
11968 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11969                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11970                 break;
11971
11972 /*
11973             case FPOINTER:
11974                 pic16_emitcode ("mov","b,a");
11975                 pic16_emitcode("movx","a,@dptr");
11976                 break;
11977
11978             case GPOINTER:
11979                 pic16_emitcode ("push","b");
11980                 pic16_emitcode ("push","acc");
11981                 pic16_emitcode ("lcall","__gptrget");
11982                 pic16_emitcode ("pop","b");
11983                 break;
11984 */
11985             default:
11986               assert(0);
11987         }
11988         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11989         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11990         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11991 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11992 //        pic16_emitcode ("orl","a,b");
11993     }
11994
11995 //    if (p_type == GPOINTER)
11996 //        pic16_emitcode("pop","b");
11997
11998     switch (p_type) {
11999
12000       case POINTER:
12001         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12002 //      pic16_emitcode("mov","@%s,a",rname);
12003         break;
12004 /*
12005       case FPOINTER:
12006         pic16_emitcode("movx","@dptr,a");
12007         break;
12008         
12009       case GPOINTER:
12010         DEBUGpic16_emitcode(";lcall","__gptrput");
12011         break;                  
12012 */
12013       default:
12014         assert(0);
12015     }
12016     
12017 //    pic16_freeAsmop(right, NULL, ic, TRUE);
12018 }
12019 /*-----------------------------------------------------------------*/
12020 /* genDataPointerSet - remat pointer to data space                 */
12021 /*-----------------------------------------------------------------*/
12022 static void genDataPointerSet(operand *right,
12023                               operand *result,
12024                               iCode *ic)
12025 {
12026     int size, offset = 0, resoffset=0 ;
12027
12028     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12029     pic16_aopOp(right,ic,FALSE);
12030
12031     size = AOP_SIZE(right);
12032
12033 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12034
12035 #if 0
12036     if ( AOP_TYPE(result) == AOP_PCODE) {
12037       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12038               AOP(result)->aopu.pcop->name,
12039                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12040               PCOR(AOP(result)->aopu.pcop)->instance:
12041               PCOI(AOP(result)->aopu.pcop)->offset);
12042     }
12043 #endif
12044
12045         if(AOP(result)->aopu.pcop->type == PO_DIR)
12046                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12047
12048         while (size--) {
12049                 if (AOP_TYPE(right) == AOP_LIT) {
12050                   unsigned int lit;
12051
12052                     if(!IS_FLOAT(operandType( right )))
12053                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12054                     else {
12055                       union {
12056                         unsigned long lit_int;
12057                         float lit_float;
12058                       } info;
12059         
12060                         /* take care if literal is a float */
12061                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12062                         lit = info.lit_int;
12063                     }
12064
12065                     lit = lit >> (8*offset);
12066                     if(lit&0xff) {
12067                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12068                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12069                     } else {
12070                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12071                     }
12072                 } else {
12073                   pic16_mov2w(AOP(right), offset);
12074                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12075                 }
12076                 offset++;
12077                 resoffset++;
12078         }
12079
12080     pic16_freeAsmop(right,NULL,ic,TRUE);
12081 }
12082
12083
12084
12085 /*-----------------------------------------------------------------*/
12086 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12087 /*-----------------------------------------------------------------*/
12088 static void genNearPointerSet (operand *right,
12089                                operand *result, 
12090                                iCode *ic)
12091 {
12092   asmop *aop = NULL;
12093   sym_link *retype;
12094   sym_link *ptype = operandType(result);
12095   sym_link *resetype;
12096     
12097         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12098         retype= getSpec(operandType(right));
12099         resetype = getSpec(operandType(result));
12100   
12101         pic16_aopOp(result,ic,FALSE);
12102     
12103         /* if the result is rematerializable &
12104          * in data space & not a bit variable */
12105         
12106         /* and result is not a bit variable */
12107         if (AOP_TYPE(result) == AOP_PCODE
12108 //              && AOP_TYPE(result) == AOP_IMMD
12109                 && DCL_TYPE(ptype) == POINTER
12110                 && !IS_BITFIELD(retype)
12111                 && !IS_BITFIELD(resetype)) {
12112
12113                 genDataPointerSet (right,result,ic);
12114                 pic16_freeAsmop(result,NULL,ic,TRUE);
12115           return;
12116         }
12117
12118         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12119         pic16_aopOp(right,ic,FALSE);
12120         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12121
12122         /* if the value is already in a pointer register
12123          * then don't need anything more */
12124         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12125           /* otherwise get a free pointer register */
12126           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12127
12128           ;
12129         }
12130
12131         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12132
12133         /* if bitfield then unpack the bits */
12134         if (IS_BITFIELD(resetype)) {
12135                 genPackBits (resetype, result, right, NULL, POINTER);
12136         } else {
12137                 /* we have can just get the values */
12138           int size = AOP_SIZE(right);
12139           int offset = 0 ;    
12140
12141             pic16_loadFSR0(result, 0);
12142             
12143                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12144                 while (size--) {
12145                                 if (AOP_TYPE(right) == AOP_LIT) {
12146                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12147                                         if (size) {
12148                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12149                                         } else {
12150                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12151                                         }
12152                                 } else { // no literal
12153                                         if(size) {
12154                                                 pic16_emitpcode(POC_MOVFF,
12155                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12156                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12157                                         } else {
12158                                                 pic16_emitpcode(POC_MOVFF,
12159                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12160                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12161                                         }
12162                                 }
12163                         offset++;
12164                 }
12165         }
12166
12167         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12168         /* now some housekeeping stuff */
12169         if (aop) {
12170           /* we had to allocate for this iCode */
12171           pic16_freeAsmop(NULL,aop,ic,TRUE);
12172         } else { 
12173           /* we did not allocate which means left
12174            * already in a pointer register, then
12175            * if size > 0 && this could be used again
12176            * we have to point it back to where it 
12177            * belongs */
12178           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12179           if (AOP_SIZE(right) > 1
12180             && !OP_SYMBOL(result)->remat
12181             && ( OP_SYMBOL(result)->liveTo > ic->seq
12182             || ic->depth )) {
12183
12184               int size = AOP_SIZE(right) - 1;
12185
12186                 while (size--)
12187                   pic16_emitcode("decf","fsr0,f");
12188                   //pic16_emitcode("dec","%s",rname);
12189             }
12190         }
12191
12192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12193     /* done */
12194 //release:
12195     pic16_freeAsmop(right,NULL,ic,TRUE);
12196     pic16_freeAsmop(result,NULL,ic,TRUE);
12197 }
12198
12199 /*-----------------------------------------------------------------*/
12200 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12201 /*-----------------------------------------------------------------*/
12202 static void genPagedPointerSet (operand *right,
12203                                operand *result, 
12204                                iCode *ic)
12205 {
12206     asmop *aop = NULL;
12207     regs *preg = NULL ;
12208     char *rname , *l;
12209     sym_link *retype;
12210        
12211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12212
12213     retype= getSpec(operandType(right));
12214     
12215     pic16_aopOp(result,ic,FALSE);
12216     
12217     /* if the value is already in a pointer register
12218        then don't need anything more */
12219     if (!AOP_INPREG(AOP(result))) {
12220         /* otherwise get a free pointer register */
12221         aop = newAsmop(0);
12222         preg = getFreePtr(ic,&aop,FALSE);
12223         pic16_emitcode("mov","%s,%s",
12224                 preg->name,
12225                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12226         rname = preg->name ;
12227     } else
12228         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12229     
12230     pic16_freeAsmop(result,NULL,ic,TRUE);
12231     pic16_aopOp (right,ic,FALSE);
12232
12233     /* if bitfield then unpack the bits */
12234     if (IS_BITFIELD(retype)) 
12235         genPackBits (retype,result,right,rname,PPOINTER);
12236     else {
12237         /* we have can just get the values */
12238         int size = AOP_SIZE(right);
12239         int offset = 0 ;        
12240         
12241         while (size--) {
12242             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12243             
12244             MOVA(l);
12245             pic16_emitcode("movx","@%s,a",rname);
12246
12247             if (size)
12248                 pic16_emitcode("inc","%s",rname);
12249
12250             offset++;
12251         }
12252     }
12253     
12254     /* now some housekeeping stuff */
12255     if (aop) {
12256         /* we had to allocate for this iCode */
12257         pic16_freeAsmop(NULL,aop,ic,TRUE);
12258     } else { 
12259         /* we did not allocate which means left
12260            already in a pointer register, then
12261            if size > 0 && this could be used again
12262            we have to point it back to where it 
12263            belongs */
12264         if (AOP_SIZE(right) > 1 &&
12265             !OP_SYMBOL(result)->remat &&
12266             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12267               ic->depth )) {
12268             int size = AOP_SIZE(right) - 1;
12269             while (size--)
12270                 pic16_emitcode("dec","%s",rname);
12271         }
12272     }
12273
12274     /* done */
12275     pic16_freeAsmop(right,NULL,ic,TRUE);
12276     
12277         
12278 }
12279
12280 /*-----------------------------------------------------------------*/
12281 /* genFarPointerSet - set value from far space                     */
12282 /*-----------------------------------------------------------------*/
12283 static void genFarPointerSet (operand *right,
12284                               operand *result, iCode *ic)
12285 {
12286     int size, offset ;
12287     sym_link *retype = getSpec(operandType(right));
12288
12289     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12290     pic16_aopOp(result,ic,FALSE);
12291
12292     /* if the operand is already in dptr 
12293     then we do nothing else we move the value to dptr */
12294     if (AOP_TYPE(result) != AOP_STR) {
12295         /* if this is remateriazable */
12296         if (AOP_TYPE(result) == AOP_IMMD)
12297             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12298         else { /* we need to get it byte by byte */
12299             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12300             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12301             if (options.model == MODEL_FLAT24)
12302             {
12303                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12304             }
12305         }
12306     }
12307     /* so dptr know contains the address */
12308     pic16_freeAsmop(result,NULL,ic,TRUE);
12309     pic16_aopOp(right,ic,FALSE);
12310
12311     /* if bit then unpack */
12312     if (IS_BITFIELD(retype)) 
12313         genPackBits(retype,result,right,"dptr",FPOINTER);
12314     else {
12315         size = AOP_SIZE(right);
12316         offset = 0 ;
12317
12318         while (size--) {
12319             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12320             MOVA(l);
12321             pic16_emitcode("movx","@dptr,a");
12322             if (size)
12323                 pic16_emitcode("inc","dptr");
12324         }
12325     }
12326
12327     pic16_freeAsmop(right,NULL,ic,TRUE);
12328 }
12329
12330 /*-----------------------------------------------------------------*/
12331 /* genGenPointerSet - set value from generic pointer space         */
12332 /*-----------------------------------------------------------------*/
12333 #if 0
12334 static void genGenPointerSet (operand *right,
12335                               operand *result, iCode *ic)
12336 {
12337         int i, size, offset, lit;
12338         sym_link *retype = getSpec(operandType(right));
12339
12340         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12341
12342         pic16_aopOp(result,ic,FALSE);
12343         pic16_aopOp(right,ic,FALSE);
12344         size = AOP_SIZE(right);
12345         offset = 0;
12346
12347         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12348
12349         /* if the operand is already in dptr 
12350                 then we do nothing else we move the value to dptr */
12351         if (AOP_TYPE(result) != AOP_STR) {
12352                 /* if this is remateriazable */
12353                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12354                 // WARNING: anythig until "else" is untested!
12355                 if (AOP_TYPE(result) == AOP_IMMD) {
12356                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12357                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12358                         // load FSR0 from immediate
12359                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12360                         offset = 0;
12361                         while(size--) {
12362                                 if(size) {
12363                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12364                                 } else {
12365                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12366                                 }
12367                                 offset++;
12368                         }
12369                         goto release;
12370                 }
12371                 else { /* we need to get it byte by byte */
12372                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12373                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12374
12375                         // set up FSR0 with address of result
12376                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12377                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12378
12379                         /* hack hack! see if this the FSR. If so don't load W */
12380                         if(AOP_TYPE(right) != AOP_ACC) {
12381
12382                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12383
12384                                 if(AOP_TYPE(right) == AOP_LIT)
12385                                 {
12386                                         // copy literal
12387                                         // note: pic16_popGet handles sign extension
12388                                         for(i=0;i<size;i++) {
12389                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12390                                                 if(i < size-1)
12391                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12392                                                 else
12393                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12394                                         }
12395                                 } else {
12396                                         // copy regs
12397
12398                                         for(i=0;i<size;i++) {
12399                                                 if(i < size-1)
12400                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12401                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12402                                                 else
12403                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12404                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12405                                         }
12406                                 }
12407                                 goto release;
12408                         } 
12409                         // right = ACC
12410                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12411                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12412                         goto release;
12413         } // if (AOP_TYPE(result) != AOP_IMMD)
12414
12415         } // if (AOP_TYPE(result) != AOP_STR)
12416         /* so dptr know contains the address */
12417
12418
12419         /* if bit then unpack */
12420         if (IS_BITFIELD(retype)) 
12421                 genPackBits(retype,result,right,"dptr",GPOINTER);
12422         else {
12423                 size = AOP_SIZE(right);
12424                 offset = 0 ;
12425
12426                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12427
12428                 // set up FSR0 with address of result
12429                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12430                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12431         
12432                 while (size--) {
12433                         if (AOP_TYPE(right) == AOP_LIT) {
12434                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12435                                 if (size) {
12436                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12437                                 } else {
12438                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12439                                 }
12440                         } else { // no literal
12441                                 if(size) {
12442                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12443                                 } else {
12444                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12445                                 }
12446                         }
12447                         offset++;
12448                 }
12449         }
12450
12451         release:
12452         pic16_freeAsmop(right,NULL,ic,TRUE);
12453         pic16_freeAsmop(result,NULL,ic,TRUE);
12454 }
12455 #endif
12456
12457 static void genGenPointerSet (operand *right,
12458                               operand *result, iCode *ic)
12459 {
12460   int size;
12461   sym_link *retype = getSpec(operandType(right));
12462   char fgptrput[32];
12463
12464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12465
12466     pic16_aopOp(result,ic,FALSE);
12467     pic16_aopOp(right,ic,FALSE);
12468     size = AOP_SIZE(right);
12469
12470     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12471
12472
12473     /* if bit then unpack */
12474     if (IS_BITFIELD(retype)) {
12475 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12476       genPackBits(retype,result,right,"dptr",GPOINTER);
12477       goto release;
12478     }
12479
12480     size = AOP_SIZE(right);
12481
12482     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12483
12484
12485
12486     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12487
12488     /* value of right+0 is placed on stack, which will be retrieved
12489      * by the support function this restoring the stack. The important
12490      * thing is that there is no need to manually restore stack pointer
12491      * here */
12492     pushaop(AOP(right), 0);
12493 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12494     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12495     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12496     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12497     
12498     /* load address to write to in WREG:FSR0H:FSR0L */
12499     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12500                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12501     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12502                                 pic16_popCopyReg(&pic16_pc_prodl)));
12503     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12504     
12505
12506     /* put code here */
12507     switch (size) {
12508       case 1: strcpy(fgptrput, "__gptrput1"); break;
12509       case 2: strcpy(fgptrput, "__gptrput2"); break;
12510       case 3: strcpy(fgptrput, "__gptrput3"); break;
12511       case 4: strcpy(fgptrput, "__gptrput4"); break;
12512       default:
12513         werror(W_POSSBUG2, __FILE__, __LINE__);
12514         abort();
12515     }
12516     
12517     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12518     
12519     {
12520       symbol *sym;
12521                   
12522         sym = newSymbol( fgptrput, 0 );
12523         sym->used++;
12524         strcpy(sym->rname, fgptrput);
12525         checkAddSym(&externs, sym);
12526     }
12527
12528 release:
12529     pic16_freeAsmop(right,NULL,ic,TRUE);
12530     pic16_freeAsmop(result,NULL,ic,TRUE);
12531 }
12532
12533 /*-----------------------------------------------------------------*/
12534 /* genPointerSet - stores the value into a pointer location        */
12535 /*-----------------------------------------------------------------*/
12536 static void genPointerSet (iCode *ic)
12537 {    
12538   operand *right, *result ;
12539   sym_link *type, *etype;
12540   int p_type;
12541
12542     FENTRY;
12543
12544     right = IC_RIGHT(ic);
12545     result = IC_RESULT(ic) ;
12546
12547     /* depending on the type of pointer we need to
12548     move it to the correct pointer register */
12549     type = operandType(result);
12550     etype = getSpec(type);
12551     /* if left is of type of pointer then it is simple */
12552     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12553         p_type = DCL_TYPE(type);
12554     }
12555     else {
12556         /* we have to go by the storage class */
12557         p_type = PTR_TYPE(SPEC_OCLS(etype));
12558
12559 /*      if (SPEC_OCLS(etype)->codesp ) { */
12560 /*          p_type = CPOINTER ;  */
12561 /*      } */
12562 /*      else */
12563 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12564 /*              p_type = FPOINTER ; */
12565 /*          else */
12566 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12567 /*                  p_type = PPOINTER ; */
12568 /*              else */
12569 /*                  if (SPEC_OCLS(etype) == idata ) */
12570 /*                      p_type = IPOINTER ; */
12571 /*                  else */
12572 /*                      p_type = POINTER ; */
12573     }
12574
12575     /* now that we have the pointer type we assign
12576     the pointer values */
12577     switch (p_type) {
12578       case POINTER:
12579       case IPOINTER:
12580         genNearPointerSet (right,result,ic);
12581         break;
12582
12583       case PPOINTER:
12584         genPagedPointerSet (right,result,ic);
12585         break;
12586
12587       case FPOINTER:
12588         genFarPointerSet (right,result,ic);
12589         break;
12590         
12591       case GPOINTER:
12592         genGenPointerSet (right,result,ic);
12593         break;
12594
12595       default:
12596         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12597           "genPointerSet: illegal pointer type");
12598     }
12599 }
12600
12601 /*-----------------------------------------------------------------*/
12602 /* genIfx - generate code for Ifx statement                        */
12603 /*-----------------------------------------------------------------*/
12604 static void genIfx (iCode *ic, iCode *popIc)
12605 {
12606   operand *cond = IC_COND(ic);
12607   int isbit =0;
12608
12609     FENTRY;
12610
12611     pic16_aopOp(cond,ic,FALSE);
12612
12613     /* get the value into acc */
12614     if (AOP_TYPE(cond) != AOP_CRY)
12615       pic16_toBoolean(cond);
12616     else
12617       isbit = 1;
12618     /* the result is now in the accumulator */
12619     pic16_freeAsmop(cond,NULL,ic,TRUE);
12620
12621     /* if there was something to be popped then do it */
12622     if (popIc)
12623       genIpop(popIc);
12624
12625     /* if the condition is  a bit variable */
12626     if (isbit && IS_ITEMP(cond) && 
12627         SPIL_LOC(cond)) {
12628       genIfxJump(ic,"c");
12629       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12630     } else {
12631       if (isbit && !IS_ITEMP(cond))
12632         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12633         else
12634         genIfxJump(ic,"a");
12635     }
12636     ic->generated = 1;
12637 }
12638
12639 /*-----------------------------------------------------------------*/
12640 /* genAddrOf - generates code for address of                       */
12641 /*-----------------------------------------------------------------*/
12642 static void genAddrOf (iCode *ic)
12643 {
12644   operand *result, *left;
12645   int size;
12646   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12647   pCodeOp *pcop0, *pcop1, *pcop2;
12648
12649     FENTRY;
12650
12651     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12652
12653     sym = OP_SYMBOL( IC_LEFT(ic) );
12654     
12655     if(sym->onStack) {
12656       /* get address of symbol on stack */
12657       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12658 #if 0
12659       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12660                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12661 #endif
12662
12663       // operands on stack are accessible via "FSR2 + index" with index
12664       // starting at 2 for arguments and growing from 0 downwards for
12665       // local variables (index == 0 is not assigned so we add one here)
12666       {
12667         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12668         if (soffs <= 0) {
12669           assert (soffs < 0);
12670           soffs++;
12671         } // if
12672         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12673         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12674         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12675         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12676         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12677         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12678         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12679       }
12680
12681       goto release;
12682     }
12683         
12684 //      if(pic16_debug_verbose) {
12685 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12686 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12687 //      }
12688         
12689     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12690     size = AOP_SIZE(IC_RESULT(ic));
12691
12692     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12693     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12694     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12695         
12696     if (size == 3) {
12697       pic16_emitpcode(POC_MOVLW, pcop0);
12698       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12699       pic16_emitpcode(POC_MOVLW, pcop1);
12700       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12701       pic16_emitpcode(POC_MOVLW, pcop2);
12702       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12703     } else
12704     if (size == 2) {
12705       pic16_emitpcode(POC_MOVLW, pcop0);
12706       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12707       pic16_emitpcode(POC_MOVLW, pcop1);
12708     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12709     } else {
12710       pic16_emitpcode(POC_MOVLW, pcop0);
12711       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12712     }
12713
12714     pic16_freeAsmop(left, NULL, ic, FALSE);
12715 release:
12716     pic16_freeAsmop(result,NULL,ic,TRUE);
12717 }
12718
12719
12720 #if 0
12721 /*-----------------------------------------------------------------*/
12722 /* genFarFarAssign - assignment when both are in far space         */
12723 /*-----------------------------------------------------------------*/
12724 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12725 {
12726     int size = AOP_SIZE(right);
12727     int offset = 0;
12728     char *l ;
12729     /* first push the right side on to the stack */
12730     while (size--) {
12731         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12732         MOVA(l);
12733         pic16_emitcode ("push","acc");
12734     }
12735     
12736     pic16_freeAsmop(right,NULL,ic,FALSE);
12737     /* now assign DPTR to result */
12738     pic16_aopOp(result,ic,FALSE);
12739     size = AOP_SIZE(result);
12740     while (size--) {
12741         pic16_emitcode ("pop","acc");
12742         pic16_aopPut(AOP(result),"a",--offset);
12743     }
12744     pic16_freeAsmop(result,NULL,ic,FALSE);
12745         
12746 }
12747 #endif
12748
12749 /*-----------------------------------------------------------------*/
12750 /* genAssign - generate code for assignment                        */
12751 /*-----------------------------------------------------------------*/
12752 static void genAssign (iCode *ic)
12753 {
12754   operand *result, *right;
12755   int size, offset,know_W;
12756   unsigned long lit = 0L;
12757
12758   result = IC_RESULT(ic);
12759   right  = IC_RIGHT(ic) ;
12760
12761   FENTRY;
12762   
12763   /* if they are the same */
12764   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12765     return ;
12766
12767   /* reversed order operands are aopOp'ed so that result operand
12768    * is effective in case right is a stack symbol. This maneauver
12769    * allows to use the _G.resDirect flag later */
12770   pic16_aopOp(result,ic,TRUE);
12771   pic16_aopOp(right,ic,FALSE);
12772
12773   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12774
12775   /* if they are the same registers */
12776   if (pic16_sameRegs(AOP(right),AOP(result)))
12777     goto release;
12778
12779   /* if the result is a bit */
12780   if (AOP_TYPE(result) == AOP_CRY) {
12781     /* if the right size is a literal then
12782        we know what the value is */
12783     if (AOP_TYPE(right) == AOP_LIT) {
12784           
12785       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12786                   pic16_popGet(AOP(result),0));
12787
12788       if (((int) operandLitValue(right))) 
12789         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12790                        AOP(result)->aopu.aop_dir,
12791                        AOP(result)->aopu.aop_dir);
12792       else
12793         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12794                        AOP(result)->aopu.aop_dir,
12795                        AOP(result)->aopu.aop_dir);
12796       goto release;
12797     }
12798
12799     /* the right is also a bit variable */
12800     if (AOP_TYPE(right) == AOP_CRY) {
12801       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12802       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12803       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12804
12805       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12806                      AOP(result)->aopu.aop_dir,
12807                      AOP(result)->aopu.aop_dir);
12808       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12809                      AOP(right)->aopu.aop_dir,
12810                      AOP(right)->aopu.aop_dir);
12811       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12812                      AOP(result)->aopu.aop_dir,
12813                      AOP(result)->aopu.aop_dir);
12814       goto release ;
12815     }
12816
12817     /* we need to or */
12818     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12819     pic16_toBoolean(right);
12820     emitSKPZ;
12821     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12822     //pic16_aopPut(AOP(result),"a",0);
12823     goto release ;
12824   }
12825
12826   /* bit variables done */
12827   /* general case */
12828   size = AOP_SIZE(result);
12829   offset = 0 ;
12830
12831   if(AOP_TYPE(right) == AOP_LIT) {
12832         if(!IS_FLOAT(operandType( right )))
12833                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12834         else {
12835            union {
12836               unsigned long lit_int;
12837               float lit_float;
12838             } info;
12839         
12840                 /* take care if literal is a float */
12841                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12842                 lit = info.lit_int;
12843         }
12844   }
12845
12846 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12847 //                      sizeof(unsigned long int), sizeof(float));
12848
12849
12850   if (AOP_TYPE(right) == AOP_REG) {
12851     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12852     while (size--) {
12853       
12854       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12855     } // while
12856     goto release;
12857   }
12858
12859   if(AOP_TYPE(right) != AOP_LIT
12860         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12861         && !IS_FUNC(OP_SYM_TYPE(right))
12862         ) {
12863         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12864         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12865
12866         // set up table pointer
12867         if(is_LitOp(right)) {
12868 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12869                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12870                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12871                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12872                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12873                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12874                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12875         } else {
12876 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12877                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12878                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12879                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12880                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12881                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12882                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12883         }
12884
12885         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12886         while(size--) {
12887                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12888                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12889                         pic16_popGet(AOP(result),offset)));
12890                 offset++;
12891         }
12892
12893         size = getSize(OP_SYM_ETYPE(right));
12894         if(AOP_SIZE(result) > size) {
12895                 size = AOP_SIZE(result) - size;
12896                 while(size--) {
12897                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12898                         offset++;
12899                 }
12900         }
12901         goto release;
12902   }
12903
12904
12905
12906 #if 0
12907 /* VR - What is this?! */
12908   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12909     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12910     if(aopIdx(AOP(result),0) == 4) {
12911
12912       /* this is a workaround to save value of right into wreg too,
12913        * value of wreg is going to be used later */
12914       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12915       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12916       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12917       goto release;
12918     } else
12919 //      assert(0);
12920       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12921   }
12922 #endif
12923
12924   know_W=-1;
12925   while (size--) {
12926   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12927     if(AOP_TYPE(right) == AOP_LIT) {
12928       if(lit&0xff) {
12929         if(know_W != (lit&0xff))
12930           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12931         know_W = lit&0xff;
12932         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12933       } else
12934         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12935
12936       lit >>= 8;
12937
12938     } else if (AOP_TYPE(right) == AOP_CRY) {
12939       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12940       if(offset == 0) {
12941         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12942         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12943         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12944       }
12945     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12946         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12947         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12948     } else {
12949       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12950
12951       if(!_G.resDirect)         /* use this aopForSym feature */
12952         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12953     }
12954             
12955     offset++;
12956   }
12957   
12958  release:
12959   pic16_freeAsmop (right,NULL,ic,FALSE);
12960   pic16_freeAsmop (result,NULL,ic,TRUE);
12961 }   
12962
12963 /*-----------------------------------------------------------------*/
12964 /* genJumpTab - generates code for jump table                       */
12965 /*-----------------------------------------------------------------*/
12966 static void genJumpTab (iCode *ic)
12967 {
12968   symbol *jtab;
12969   char *l;
12970   pCodeOp *jt_offs;
12971   pCodeOp *jt_offs_hi;
12972   pCodeOp *jt_label;
12973
12974     FENTRY;
12975
12976     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12977     /* get the condition into accumulator */
12978     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12979     MOVA(l);
12980     /* multiply by three */
12981     pic16_emitcode("add","a,acc");
12982     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12983
12984     jtab = newiTempLabel(NULL);
12985     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12986     pic16_emitcode("jmp","@a+dptr");
12987     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12988
12989 #if 0
12990     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12991     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12992     emitSKPNC;
12993     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12994     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12995     pic16_emitpLabel(jtab->key);
12996
12997 #else
12998
12999     jt_offs = pic16_popGetTempReg(0);
13000     jt_offs_hi = pic16_popGetTempReg(1);
13001     jt_label = pic16_popGetLabel (jtab->key);
13002     //fprintf (stderr, "Creating jump table...\n");
13003
13004     // calculate offset into jump table (idx * sizeof (GOTO))
13005     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
13006     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13007     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13008     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13009     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13010     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13011     pic16_emitpcode(POC_MOVWF , jt_offs);
13012
13013     // prepare PCLATx (set to first entry in jump table)
13014     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13015     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13016     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13017     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13018     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13019
13020     // set PCLATx to selected entry (new PCL is stored in jt_offs)
13021     pic16_emitpcode(POC_ADDWF , jt_offs);
13022     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13023     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13024     emitSKPNC;
13025     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
13026
13027     // release temporaries and prepare jump into table (new PCL --> WREG)
13028     pic16_emitpcode(POC_MOVFW , jt_offs);
13029     pic16_popReleaseTempReg (jt_offs_hi, 1);
13030     pic16_popReleaseTempReg (jt_offs, 0);
13031
13032     // jump into the table
13033     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13034
13035     pic16_emitpLabelFORCE(jtab->key);
13036
13037 #endif
13038     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13039
13040     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13041     /* now generate the jump labels */
13042     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13043          jtab = setNextItem(IC_JTLABELS(ic))) {
13044 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13045         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13046         
13047     }
13048     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13049
13050 }
13051
13052 /*-----------------------------------------------------------------*/
13053 /* genMixedOperation - gen code for operators between mixed types  */
13054 /*-----------------------------------------------------------------*/
13055 /*
13056   TSD - Written for the PIC port - but this unfortunately is buggy.
13057   This routine is good in that it is able to efficiently promote 
13058   types to different (larger) sizes. Unfortunately, the temporary
13059   variables that are optimized out by this routine are sometimes
13060   used in other places. So until I know how to really parse the 
13061   iCode tree, I'm going to not be using this routine :(.
13062 */
13063 static int genMixedOperation (iCode *ic)
13064 {
13065 #if 0
13066   operand *result = IC_RESULT(ic);
13067   sym_link *ctype = operandType(IC_LEFT(ic));
13068   operand *right = IC_RIGHT(ic);
13069   int ret = 0;
13070   int big,small;
13071   int offset;
13072
13073   iCode *nextic;
13074   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13075
13076   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13077
13078   nextic = ic->next;
13079   if(!nextic)
13080     return 0;
13081
13082   nextright = IC_RIGHT(nextic);
13083   nextleft  = IC_LEFT(nextic);
13084   nextresult = IC_RESULT(nextic);
13085
13086   pic16_aopOp(right,ic,FALSE);
13087   pic16_aopOp(result,ic,FALSE);
13088   pic16_aopOp(nextright,  nextic, FALSE);
13089   pic16_aopOp(nextleft,   nextic, FALSE);
13090   pic16_aopOp(nextresult, nextic, FALSE);
13091
13092   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13093
13094     operand *t = right;
13095     right = nextright;
13096     nextright = t; 
13097
13098     pic16_emitcode(";remove right +","");
13099
13100   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13101 /*
13102     operand *t = right;
13103     right = nextleft;
13104     nextleft = t; 
13105 */
13106     pic16_emitcode(";remove left +","");
13107   } else
13108     return 0;
13109
13110   big = AOP_SIZE(nextleft);
13111   small = AOP_SIZE(nextright);
13112
13113   switch(nextic->op) {
13114
13115   case '+':
13116     pic16_emitcode(";optimize a +","");
13117     /* if unsigned or not an integral type */
13118     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13119       pic16_emitcode(";add a bit to something","");
13120     } else {
13121
13122       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13123
13124       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13125         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13126         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13127       } else
13128         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13129
13130       offset = 0;
13131       while(--big) {
13132
13133         offset++;
13134
13135         if(--small) {
13136           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13137             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13138             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13139           }
13140
13141           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13142           emitSKPNC;
13143           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13144                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13145                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13146           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13147           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13148
13149         } else {
13150           pic16_emitcode("rlf","known_zero,w");
13151
13152           /*
13153             if right is signed
13154               btfsc  right,7
13155                addlw ff
13156           */
13157           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13158             pic16_emitcode("addwf","%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           } else {
13161             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13162           }
13163         }
13164       }
13165       ret = 1;
13166     }
13167   }
13168   ret = 1;
13169
13170 release:
13171   pic16_freeAsmop(right,NULL,ic,TRUE);
13172   pic16_freeAsmop(result,NULL,ic,TRUE);
13173   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13174   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13175   if(ret)
13176     nextic->generated = 1;
13177
13178   return ret;
13179 #else
13180   return 0;
13181 #endif
13182 }
13183 /*-----------------------------------------------------------------*/
13184 /* genCast - gen code for casting                                  */
13185 /*-----------------------------------------------------------------*/
13186 static void genCast (iCode *ic)
13187 {
13188   operand *result = IC_RESULT(ic);
13189   sym_link *ctype = operandType(IC_LEFT(ic));
13190   sym_link *rtype = operandType(IC_RIGHT(ic));
13191   sym_link *restype = operandType(IC_RESULT(ic));
13192   operand *right = IC_RIGHT(ic);
13193   int size, offset ;
13194
13195
13196     FENTRY;
13197
13198         /* if they are equivalent then do nothing */
13199 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13200 //              return ;
13201
13202         pic16_aopOp(right,ic,FALSE) ;
13203         pic16_aopOp(result,ic,FALSE);
13204
13205         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13206
13207
13208         /* if the result is a bit */
13209         if (AOP_TYPE(result) == AOP_CRY) {
13210         
13211                 /* if the right size is a literal then
13212                  * we know what the value is */
13213                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13214
13215                 if (AOP_TYPE(right) == AOP_LIT) {
13216                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13217                                 pic16_popGet(AOP(result),0));
13218
13219                         if (((int) operandLitValue(right))) 
13220                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13221                                         AOP(result)->aopu.aop_dir,
13222                                         AOP(result)->aopu.aop_dir);
13223                         else
13224                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13225                                         AOP(result)->aopu.aop_dir,
13226                                         AOP(result)->aopu.aop_dir);
13227                         goto release;
13228                 }
13229
13230                 /* the right is also a bit variable */
13231                 if (AOP_TYPE(right) == AOP_CRY) {
13232                         emitCLRC;
13233                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13234
13235                         pic16_emitcode("clrc","");
13236                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13237                                 AOP(right)->aopu.aop_dir,
13238                                 AOP(right)->aopu.aop_dir);
13239                         pic16_aopPut(AOP(result),"c",0);
13240                         goto release ;
13241                 }
13242
13243                 /* we need to or */
13244                 if (AOP_TYPE(right) == AOP_REG) {
13245                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13246                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13247                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13248                 }
13249                 pic16_toBoolean(right);
13250                 pic16_aopPut(AOP(result),"a",0);
13251                 goto release ;
13252         }
13253
13254         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13255           int offset = 1;
13256
13257                 size = AOP_SIZE(result);
13258
13259                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13260
13261                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13262                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13263                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13264
13265                 while (size--)
13266                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13267
13268                 goto release;
13269         }
13270
13271         if(IS_BITFIELD(getSpec(restype))
13272           && IS_BITFIELD(getSpec(rtype))) {
13273           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13274         }
13275
13276         /* if they are the same size : or less */
13277         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13278
13279                 /* if they are in the same place */
13280                 if (pic16_sameRegs(AOP(right),AOP(result)))
13281                         goto release;
13282
13283                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13284 #if 0
13285                 if (IS_PTR_CONST(rtype))
13286 #else
13287                 if (IS_CODEPTR(rtype))
13288 #endif
13289                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13290
13291 #if 0
13292                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13293 #else
13294                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13295 #endif
13296                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13297
13298 #if 0
13299                 if(AOP_TYPE(right) == AOP_IMMD) {
13300                   pCodeOp *pcop0, *pcop1, *pcop2;
13301                   symbol *sym = OP_SYMBOL( right );
13302
13303                         size = AOP_SIZE(result);
13304                         /* low */
13305                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13306                         /* high */
13307                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13308                         /* upper */
13309                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13310         
13311                         if (size == 3) {
13312                                 pic16_emitpcode(POC_MOVLW, pcop0);
13313                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13314                                 pic16_emitpcode(POC_MOVLW, pcop1);
13315                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13316                                 pic16_emitpcode(POC_MOVLW, pcop2);
13317                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13318                         } else
13319                         if (size == 2) {
13320                                 pic16_emitpcode(POC_MOVLW, pcop0);
13321                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13322                                 pic16_emitpcode(POC_MOVLW, pcop1);
13323                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13324                         } else {
13325                                 pic16_emitpcode(POC_MOVLW, pcop0);
13326                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13327                         }
13328                 } else
13329 #endif
13330                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13331                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13332                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13333                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13334                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13335                         if(AOP_SIZE(result) <2)
13336                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13337                 } else {
13338                         /* if they in different places then copy */
13339                         size = AOP_SIZE(result);
13340                         offset = 0 ;
13341                         while (size--) {
13342                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13343                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13344                                 offset++;
13345                         }
13346                 }
13347                 goto release;
13348         }
13349
13350         /* if the result is of type pointer */
13351         if (IS_PTR(ctype)) {
13352           int p_type;
13353           sym_link *type = operandType(right);
13354           sym_link *etype = getSpec(type);
13355
13356                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13357
13358                 /* pointer to generic pointer */
13359                 if (IS_GENPTR(ctype)) {
13360                   char *l = zero;
13361             
13362                         if (IS_PTR(type)) 
13363                                 p_type = DCL_TYPE(type);
13364                         else {
13365                 /* we have to go by the storage class */
13366                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13367
13368 /*              if (SPEC_OCLS(etype)->codesp )  */
13369 /*                  p_type = CPOINTER ;  */
13370 /*              else */
13371 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13372 /*                      p_type = FPOINTER ; */
13373 /*                  else */
13374 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13375 /*                          p_type = PPOINTER; */
13376 /*                      else */
13377 /*                          if (SPEC_OCLS(etype) == idata ) */
13378 /*                              p_type = IPOINTER ; */
13379 /*                          else */
13380 /*                              p_type = POINTER ; */
13381             }
13382                 
13383             /* the first two bytes are known */
13384       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13385             size = GPTRSIZE - 1; 
13386             offset = 0 ;
13387             while (size--) {
13388               if(offset < AOP_SIZE(right)) {
13389                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13390                 mov2f(AOP(result), AOP(right), offset);
13391 /*
13392                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13393                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13394                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13395                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13396                 } else { 
13397                   
13398                   pic16_aopPut(AOP(result),
13399                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13400                          offset);
13401                 }
13402 */
13403               } else 
13404                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13405               offset++;
13406             }
13407             /* the last byte depending on type */
13408             switch (p_type) {
13409             case IPOINTER:
13410             case POINTER:
13411                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13412                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13413 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13414                 break;
13415
13416             case CPOINTER:
13417                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13418                 break;
13419
13420             case FPOINTER:
13421               pic16_emitcode(";BUG!? ","%d",__LINE__);
13422                 l = one;
13423                 break;
13424             case PPOINTER:
13425               pic16_emitcode(";BUG!? ","%d",__LINE__);
13426                 l = "#0x03";
13427                 break;
13428
13429             case GPOINTER:
13430                 if (GPTRSIZE > AOP_SIZE(right)) {
13431                   // assume data pointer... THIS MIGHT BE WRONG!
13432                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13433                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13434                 } else {
13435                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13436                 }
13437               break;
13438               
13439             default:
13440                 /* this should never happen */
13441                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13442                        "got unknown pointer type");
13443                 exit(1);
13444             }
13445             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13446             goto release ;
13447         }
13448         
13449         /* just copy the pointers */
13450         size = AOP_SIZE(result);
13451         offset = 0 ;
13452         while (size--) {
13453             pic16_aopPut(AOP(result),
13454                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13455                    offset);
13456             offset++;
13457         }
13458         goto release ;
13459     }
13460     
13461
13462
13463     /* so we now know that the size of destination is greater
13464     than the size of the source.
13465     Now, if the next iCode is an operator then we might be
13466     able to optimize the operation without performing a cast.
13467     */
13468     if(genMixedOperation(ic))
13469       goto release;
13470
13471     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13472     
13473     /* we move to result for the size of source */
13474     size = AOP_SIZE(right);
13475     offset = 0 ;
13476     while (size--) {
13477       mov2f(AOP(result), AOP(right), offset);
13478       offset++;
13479     }
13480
13481     /* now depending on the sign of the destination */
13482     size = AOP_SIZE(result) - AOP_SIZE(right);
13483     /* if unsigned or not an integral type */
13484     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13485       while (size--)
13486         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13487     } else {
13488       /* we need to extend the sign :( */
13489
13490       if(size == 1) {
13491         /* Save one instruction of casting char to int */
13492         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13493         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13494         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13495       } else {
13496         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13497
13498         if(offset)
13499           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13500         else
13501           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13502         
13503         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13504
13505         while (size--)
13506           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13507       }
13508     }
13509
13510 release:
13511     pic16_freeAsmop(right,NULL,ic,TRUE);
13512     pic16_freeAsmop(result,NULL,ic,TRUE);
13513
13514 }
13515
13516 /*-----------------------------------------------------------------*/
13517 /* genDjnz - generate decrement & jump if not zero instrucion      */
13518 /*-----------------------------------------------------------------*/
13519 static int genDjnz (iCode *ic, iCode *ifx)
13520 {
13521     symbol *lbl, *lbl1;
13522     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13523
13524     if (!ifx)
13525         return 0;
13526     
13527     /* if the if condition has a false label
13528        then we cannot save */
13529     if (IC_FALSE(ifx))
13530         return 0;
13531
13532     /* if the minus is not of the form 
13533        a = a - 1 */
13534     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13535         !IS_OP_LITERAL(IC_RIGHT(ic)))
13536         return 0;
13537
13538     if (operandLitValue(IC_RIGHT(ic)) != 1)
13539         return 0;
13540
13541     /* if the size of this greater than one then no
13542        saving */
13543     if (getSize(operandType(IC_RESULT(ic))) > 1)
13544         return 0;
13545
13546     /* otherwise we can save BIG */
13547     lbl = newiTempLabel(NULL);
13548     lbl1= newiTempLabel(NULL);
13549
13550     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13551     
13552     if (IS_AOP_PREG(IC_RESULT(ic))) {
13553         pic16_emitcode("dec","%s",
13554                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13555         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13556         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13557     } else {    
13558
13559
13560       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13561       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13562
13563       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13564       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13565
13566     }
13567     
13568     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13569     ifx->generated = 1;
13570     return 1;
13571 }
13572
13573 /*-----------------------------------------------------------------*/
13574 /* genReceive - generate code for a receive iCode                  */
13575 /*-----------------------------------------------------------------*/
13576 static void genReceive (iCode *ic)
13577 {    
13578
13579   FENTRY;
13580
13581 #if 0
13582   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13583         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13584 #endif
13585 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13586
13587   if (isOperandInFarSpace(IC_RESULT(ic))
13588       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13589           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13590
13591     int size = getSize(operandType(IC_RESULT(ic)));
13592     int offset =  pic16_fReturnSizePic - size;
13593
13594       assert( 0 );
13595       while (size--) {
13596         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13597                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13598                       offset++;
13599         }
13600
13601       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13602
13603       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13604       size = AOP_SIZE(IC_RESULT(ic));
13605       offset = 0;
13606       while (size--) {
13607         pic16_emitcode ("pop","acc");
13608         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13609       }
13610   } else {
13611     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13612     _G.accInUse++;
13613     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13614     _G.accInUse--;
13615
13616     /* set pseudo stack pointer to where it should be - dw*/
13617     GpsuedoStkPtr = ic->parmBytes;
13618
13619     /* setting GpsuedoStkPtr has side effects here: */
13620     assignResultValue(IC_RESULT(ic), 0);
13621   }
13622
13623   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13624 }
13625
13626 /*-----------------------------------------------------------------*/
13627 /* genDummyRead - generate code for dummy read of volatiles        */
13628 /*-----------------------------------------------------------------*/
13629 static void
13630 genDummyRead (iCode * ic)
13631 {
13632   operand *op;
13633   int i;
13634
13635   op = IC_RIGHT(ic);
13636   if (op && IS_SYMOP(op)) {
13637     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13638       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13639       return;
13640     }
13641     pic16_aopOp (op, ic, FALSE);
13642     for (i=0; i < AOP_SIZE(op); i++) {
13643       // may need to protect this from the peepholer -- this is not nice but works...
13644       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13645       pic16_mov2w (AOP(op),i);
13646       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13647     } // for i
13648     pic16_freeAsmop (op, NULL, ic, TRUE);
13649   } else if (op) {
13650     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13651   } // if
13652 }
13653
13654 /*-----------------------------------------------------------------*/
13655 /* genpic16Code - generate code for pic16 based controllers        */
13656 /*-----------------------------------------------------------------*/
13657 /*
13658  * At this point, ralloc.c has gone through the iCode and attempted
13659  * to optimize in a way suitable for a PIC. Now we've got to generate
13660  * PIC instructions that correspond to the iCode.
13661  *
13662  * Once the instructions are generated, we'll pass through both the
13663  * peep hole optimizer and the pCode optimizer.
13664  *-----------------------------------------------------------------*/
13665
13666 void genpic16Code (iCode *lic)
13667 {
13668   iCode *ic;
13669   int cln = 0;
13670
13671     lineHead = lineCurr = NULL;
13672
13673     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13674     pic16_addpBlock(pb);
13675
13676 #if 0
13677     /* if debug information required */
13678     if (options.debug && currFunc) {
13679       if (currFunc) {
13680         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13681       }
13682     }
13683 #endif
13684
13685     for (ic = lic ; ic ; ic = ic->next ) {
13686
13687       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13688       if ( cln != ic->lineno ) {
13689         if ( options.debug ) {
13690           debugFile->writeCLine (ic);
13691         }
13692         
13693         if(!options.noCcodeInAsm) {
13694           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13695               printCLine(ic->filename, ic->lineno)));
13696         }
13697
13698         cln = ic->lineno ;
13699       }
13700         
13701       if(options.iCodeInAsm) {
13702         char *l;
13703
13704           /* insert here code to print iCode as comment */
13705           l = Safe_strdup(printILine(ic));
13706           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13707       }
13708         
13709       /* if the result is marked as
13710        * spilt and rematerializable or code for
13711        * this has already been generated then
13712        * do nothing */
13713       if (resultRemat(ic) || ic->generated ) 
13714         continue ;
13715         
13716       /* depending on the operation */
13717       switch (ic->op) {
13718         case '!' :
13719           pic16_genNot(ic);
13720           break;
13721             
13722         case '~' :
13723           pic16_genCpl(ic);
13724           break;
13725             
13726         case UNARYMINUS:
13727           genUminus (ic);
13728           break;
13729             
13730         case IPUSH:
13731           genIpush (ic);
13732           break;
13733             
13734         case IPOP:
13735           /* IPOP happens only when trying to restore a 
13736            * spilt live range, if there is an ifx statement
13737            * following this pop then the if statement might
13738            * be using some of the registers being popped which
13739            * would destroy the contents of the register so
13740            * we need to check for this condition and handle it */
13741            if (ic->next
13742              && ic->next->op == IFX
13743              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13744                genIfx (ic->next,ic);
13745           else
13746             genIpop (ic);
13747           break; 
13748             
13749         case CALL:
13750           genCall (ic);
13751           break;
13752             
13753         case PCALL:
13754           genPcall (ic);
13755           break;
13756             
13757         case FUNCTION:
13758           genFunction (ic);
13759           break;
13760             
13761         case ENDFUNCTION:
13762           genEndFunction (ic);
13763           break;
13764             
13765         case RETURN:
13766           genRet (ic);
13767           break;
13768             
13769         case LABEL:
13770           genLabel (ic);
13771           break;
13772             
13773         case GOTO:
13774           genGoto (ic);
13775           break;
13776             
13777         case '+' :
13778           pic16_genPlus (ic) ;
13779           break;
13780             
13781         case '-' :
13782           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13783             pic16_genMinus (ic);
13784           break;
13785
13786         case '*' :
13787           genMult (ic);
13788           break;
13789             
13790         case '/' :
13791           genDiv (ic) ;
13792           break;
13793             
13794         case '%' :
13795           genMod (ic);
13796           break;
13797             
13798         case '>' :
13799           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13800           break;
13801             
13802         case '<' :
13803           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13804           break;
13805             
13806         case LE_OP:
13807         case GE_OP:
13808         case NE_OP:
13809           /* note these two are xlated by algebraic equivalence
13810            * during parsing SDCC.y */
13811           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13812             "got '>=' or '<=' shouldn't have come here");
13813           break;
13814
13815         case EQ_OP:
13816           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13817           break;            
13818             
13819         case AND_OP:
13820           genAndOp (ic);
13821           break;
13822             
13823         case OR_OP:
13824           genOrOp (ic);
13825           break;
13826             
13827         case '^' :
13828           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13829           break;
13830             
13831         case '|' :
13832           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13833           break;
13834             
13835         case BITWISEAND:
13836           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13837           break;
13838             
13839         case INLINEASM:
13840           genInline (ic);
13841           break;
13842             
13843         case RRC:
13844           genRRC (ic);
13845           break;
13846             
13847         case RLC:
13848           genRLC (ic);
13849           break;
13850             
13851         case GETHBIT:
13852           genGetHbit (ic);
13853           break;
13854             
13855         case LEFT_OP:
13856           genLeftShift (ic);
13857           break;
13858             
13859         case RIGHT_OP:
13860           genRightShift (ic);
13861           break;
13862             
13863         case GET_VALUE_AT_ADDRESS:
13864           genPointerGet(ic);
13865           break;
13866             
13867         case '=' :
13868           if (POINTER_SET(ic))
13869             genPointerSet(ic);
13870           else
13871             genAssign(ic);
13872           break;
13873             
13874         case IFX:
13875           genIfx (ic,NULL);
13876           break;
13877             
13878         case ADDRESS_OF:
13879           genAddrOf (ic);
13880           break;
13881             
13882         case JUMPTABLE:
13883           genJumpTab (ic);
13884           break;
13885             
13886         case CAST:
13887           genCast (ic);
13888           break;
13889             
13890         case RECEIVE:
13891           genReceive(ic);
13892           break;
13893             
13894         case SEND:
13895           addSet(&_G.sendSet,ic);
13896           break;
13897
13898         case DUMMY_READ_VOLATILE:
13899           genDummyRead (ic);
13900           break;
13901
13902         default :
13903           ic = ic;
13904       }
13905     }
13906
13907
13908     /* now we are ready to call the
13909        peep hole optimizer */
13910     if (!options.nopeep)
13911       peepHole (&lineHead);
13912
13913     /* now do the actual printing */
13914     printLine (lineHead, codeOutFile);
13915
13916 #ifdef PCODE_DEBUG
13917     DFPRINTF((stderr,"printing pBlock\n\n"));
13918     pic16_printpBlock(stdout,pb);
13919 #endif
13920
13921     return;
13922 }
13923