* src/pic16/gen.c (genRightShiftLiteral): fixed bug #1154256
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 /* Set the following to 1 to enable the slower/bigger
51  * but more robust generic shifting routine (which also
52  * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
54
55 /* Set the following to 1 to enable the new
56  * stripped down genCmp version.
57  * This version should be easier to understand,
58  * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
60
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
140
141 static char *accUse[] = {"WREG"};
142
143 //static short rbank = -1;
144
145 static struct {
146     short r0Pushed;
147     short r1Pushed;
148     short fsr0Pushed;
149     short accInUse;
150     short inLine;
151     short debugLine;
152     short nRegsSaved;
153     short ipushRegs;
154     set *sendSet;
155     set *stackRegSet;
156     int usefastretfie;
157     bitVect *fregsUsed;
158     int stack_lat;                      /* stack offset latency */
159     int resDirect;
160     int useWreg;                        /* flag when WREG is used to pass function parameter */
161 } _G;
162
163 /* Resolved ifx structure. This structure stores information
164    about an iCode ifx that makes it easier to generate code.
165 */
166 typedef struct resolvedIfx {
167   symbol *lbl;     /* pointer to a label */
168   int condition;   /* true or false ifx */
169   int generated;   /* set true when the code associated with the ifx
170                     * is generated */
171 } resolvedIfx;
172
173 extern int pic16_ptrRegReq ;
174 extern int pic16_nRegs;
175 extern FILE *codeOutFile;
176 //static void saverbank (int, iCode *,bool);
177
178 static lineNode *lineHead = NULL;
179 static lineNode *lineCurr = NULL;
180
181 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
182 0xE0, 0xC0, 0x80, 0x00};
183 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
185
186 static  pBlock *pb;
187
188 /*-----------------------------------------------------------------*/
189 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
190 /*                 exponent of 2 is returned, otherwise -1 is      */
191 /*                 returned.                                       */
192 /* note that this is similar to the function `powof2' in SDCCsymt  */
193 /* if(n == 2^y)                                                    */
194 /*   return y;                                                     */
195 /* return -1;                                                      */
196 /*-----------------------------------------------------------------*/
197 int pic16_my_powof2 (unsigned long num)
198 {
199   if(num) {
200     if( (num & (num-1)) == 0) {
201       int nshifts = -1;
202       while(num) {
203         num>>=1;
204         nshifts++;
205       }
206       return nshifts;
207     }
208   }
209
210   return -1;
211 }
212
213 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
214 {
215   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
216                        line_no,
217                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
218                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
219                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
220                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
221                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
222                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
223                        ((result) ? AOP_SIZE(result) : 0));
224 }
225
226 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
227 {
228
229   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
230                        line_no,
231                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
232                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
233                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
234                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
235                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
236                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
237
238 }
239
240 void pic16_emitpcomment (char *fmt, ...)
241 {
242     va_list ap;
243     char lb[INITIAL_INLINEASM];  
244     char *lbp = lb;
245
246     va_start(ap,fmt);   
247
248     lb[0] = ';';
249     vsprintf(lb+1,fmt,ap);
250
251     while (isspace(*lbp)) lbp++;
252
253     if (lbp && *lbp) 
254         lineCurr = (lineCurr ?
255                     connectLine(lineCurr,newLineNode(lb)) :
256                     (lineHead = newLineNode(lb)));
257     lineCurr->isInline = _G.inLine;
258     lineCurr->isDebug  = _G.debugLine;
259
260     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
261     va_end(ap);
262
263 //      fprintf(stderr, "%s\n", lb);
264 }
265
266 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
267 {
268     va_list ap;
269     char lb[INITIAL_INLINEASM];  
270     char *lbp = lb;
271
272     if(!pic16_debug_verbose)
273       return;
274
275     va_start(ap,fmt);   
276
277     if (inst && *inst) {
278         if (fmt && *fmt)
279             sprintf(lb,"%s\t",inst);
280         else
281             sprintf(lb,"%s",inst);
282         vsprintf(lb+(strlen(lb)),fmt,ap);
283     }  else
284         vsprintf(lb,fmt,ap);
285
286     while (isspace(*lbp)) lbp++;
287
288     if (lbp && *lbp) 
289         lineCurr = (lineCurr ?
290                     connectLine(lineCurr,newLineNode(lb)) :
291                     (lineHead = newLineNode(lb)));
292     lineCurr->isInline = _G.inLine;
293     lineCurr->isDebug  = _G.debugLine;
294
295     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
296     va_end(ap);
297
298 //      fprintf(stderr, "%s\n", lb);
299 }
300
301
302
303 void pic16_emitpLabel(int key)
304 {
305   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
306 }
307
308 void pic16_emitpLabelFORCE(int key)
309 {
310   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
311 }
312
313 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
314 {
315
316   if(pcop)
317     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
318   else
319     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
320 }
321
322 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
323 {
324   if(pcop)
325     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
326   else
327     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
328 }
329   
330 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
331 {
332
333   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
334
335 }
336
337
338 #if 1
339 #define pic16_emitcode  DEBUGpic16_emitcode
340 #else
341 /*-----------------------------------------------------------------*/
342 /* pic16_emitcode - writes the code into a file : for now it is simple    */
343 /*-----------------------------------------------------------------*/
344 void pic16_emitcode (char *inst,char *fmt, ...)
345 {
346     va_list ap;
347     char lb[INITIAL_INLINEASM];  
348     char *lbp = lb;
349
350     va_start(ap,fmt);   
351
352     if (inst && *inst) {
353         if (fmt && *fmt)
354             sprintf(lb,"%s\t",inst);
355         else
356             sprintf(lb,"%s",inst);
357         vsprintf(lb+(strlen(lb)),fmt,ap);
358     }  else
359         vsprintf(lb,fmt,ap);
360
361     while (isspace(*lbp)) lbp++;
362
363     if (lbp && *lbp) 
364         lineCurr = (lineCurr ?
365                     connectLine(lineCurr,newLineNode(lb)) :
366                     (lineHead = newLineNode(lb)));
367     lineCurr->isInline = _G.inLine;
368     lineCurr->isDebug  = _G.debugLine;
369
370 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
371
372 //    if(pic16_debug_verbose)
373 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
374
375     va_end(ap);
376 }
377 #endif
378
379
380 /*-----------------------------------------------------------------*/
381 /* pic16_emitDebuggerSymbol - associate the current code location  */
382 /*   with a debugger symbol                                        */
383 /*-----------------------------------------------------------------*/
384 void
385 pic16_emitDebuggerSymbol (char * debugSym)
386 {
387   _G.debugLine = 1;
388   pic16_emitcode (";", "%s ==.", debugSym);
389   _G.debugLine = 0;
390 }
391
392
393 /*-----------------------------------------------------------------*/
394 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
395 /*-----------------------------------------------------------------*/
396 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
397 {
398 //    bool r0iu = FALSE , r1iu = FALSE;
399 //    bool r0ou = FALSE , r1ou = FALSE;
400     bool fsr0iu = FALSE, fsr0ou;
401     bool fsr2iu = FALSE, fsr2ou;
402     
403     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
404
405     
406     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
407     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
408     
409     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
410     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
411
412     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
413         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
414         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
415     }
416
417     if(!fsr0iu && !fsr0ou) {
418         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
419         (*aopp)->type = AOP_FSR0;
420
421         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
422         
423       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
424     }
425
426 #if 0
427     /* no usage of FSR2 */
428     if(!fsr2iu && !fsr2ou) {
429         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
430         (*aopp)->type = AOP_FSR2;
431
432       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
433     }
434 #endif
435         
436     /* now we know they both have usage */
437     /* if fsr0 not used in this instruction */
438     if (!fsr0iu) {
439         if (!_G.fsr0Pushed) {
440                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
441                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
442                 _G.fsr0Pushed++;
443         }
444
445         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
446         (*aopp)->type = AOP_FSR0;
447
448 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
449
450       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
451     }
452         
453
454     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
455     assert( 0 );
456
457     return NULL;
458 #if 0
459     /* the logic: if r0 & r1 used in the instruction
460     then we are in trouble otherwise */
461
462     /* first check if r0 & r1 are used by this
463     instruction, in which case we are in trouble */
464     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
465         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
466     {
467         goto endOfWorld;      
468     }
469
470     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
471     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
472
473     /* if no usage of r0 then return it */
474     if (!r0iu && !r0ou) {
475         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
476         (*aopp)->type = AOP_R0; 
477         
478         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
479     }
480
481     /* if no usage of r1 then return it */
482     if (!r1iu && !r1ou) {
483         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
484         (*aopp)->type = AOP_R1;
485
486         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
487     }    
488
489     /* now we know they both have usage */
490     /* if r0 not used in this instruction */
491     if (!r0iu) {
492         /* push it if not already pushed */
493         if (!_G.r0Pushed) {
494           //pic16_emitcode ("push","%s",
495           //          pic16_regWithIdx(R0_IDX)->dname);
496             _G.r0Pushed++ ;
497         }
498         
499         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
500         (*aopp)->type = AOP_R0;
501
502         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
503     }
504
505     /* if r1 not used then */
506
507     if (!r1iu) {
508         /* push it if not already pushed */
509         if (!_G.r1Pushed) {
510           //pic16_emitcode ("push","%s",
511           //          pic16_regWithIdx(R1_IDX)->dname);
512             _G.r1Pushed++ ;
513         }
514         
515         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
516         (*aopp)->type = AOP_R1;
517         return pic16_regWithIdx(R1_IDX);
518     }
519
520 endOfWorld :
521     /* I said end of world but not quite end of world yet */
522     /* if this is a result then we can push it on the stack*/
523     if (result) {
524         (*aopp)->type = AOP_STK;    
525         return NULL;
526     }
527
528     /* other wise this is true end of the world */
529     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
530            "getFreePtr should never reach here");
531     exit(0);
532 #endif
533 }
534
535 /*-----------------------------------------------------------------*/
536 /* newAsmop - creates a new asmOp                                  */
537 /*-----------------------------------------------------------------*/
538 static asmop *newAsmop (short type)
539 {
540     asmop *aop;
541
542     aop = Safe_calloc(1,sizeof(asmop));
543     aop->type = type;
544     return aop;
545 }
546
547 static void genSetDPTR(int n)
548 {
549     if (!n)
550     {
551         pic16_emitcode(";", "Select standard DPTR");
552         pic16_emitcode("mov", "dps, #0x00");
553     }
554     else
555     {
556         pic16_emitcode(";", "Select alternate DPTR");
557         pic16_emitcode("mov", "dps, #0x01");
558     }
559 }
560
561 /*-----------------------------------------------------------------*/
562 /* resolveIfx - converts an iCode ifx into a form more useful for  */
563 /*              generating code                                    */
564 /*-----------------------------------------------------------------*/
565 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
566 {
567   FENTRY2;
568   
569 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
570
571   if(!resIfx) 
572     return;
573
574
575   resIfx->condition = 1;    /* assume that the ifx is true */
576   resIfx->generated = 0;    /* indicate that the ifx has not been used */
577
578   if(!ifx) {
579     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
580
581 #if 1
582     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
583                         __FUNCTION__,__LINE__,resIfx->lbl->key);
584 #endif
585
586   } else {
587     if(IC_TRUE(ifx)) {
588       resIfx->lbl = IC_TRUE(ifx);
589     } else {
590       resIfx->lbl = IC_FALSE(ifx);
591       resIfx->condition = 0;
592     }
593
594 #if 1
595     if(IC_TRUE(ifx)) 
596       DEBUGpic16_emitcode("; +++","ifx true is non-null");
597     else
598       DEBUGpic16_emitcode("; +++","ifx true is null");
599     if(IC_FALSE(ifx)) 
600       DEBUGpic16_emitcode("; +++","ifx false is non-null");
601     else
602       DEBUGpic16_emitcode("; +++","ifx false is null");
603 #endif
604   }
605
606   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
607
608 }
609 #if 0
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type               */
612 /*-----------------------------------------------------------------*/
613 static int pointerCode (sym_link *etype)
614 {
615
616     return PTR_TYPE(SPEC_OCLS(etype));
617
618 }
619 #endif
620
621 /*-----------------------------------------------------------------*/
622 /* aopForSym - for a true symbol                                   */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForSym (iCode *ic, operand *op, bool result)
625 {
626     symbol *sym=OP_SYMBOL(op);
627     asmop *aop;
628     memmap *space= SPEC_OCLS(sym->etype);
629
630     FENTRY2;
631     
632     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
633     
634 //    sym = OP_SYMBOL(op);
635
636     /* if already has one */
637     if (sym->aop) {
638             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
639         return sym->aop;
640     }
641
642 #if 0
643     /* if symbol was initially placed onStack then we must re-place it
644      * to direct memory, since pic16 does not have a specific stack */
645     if(sym->onStack) {
646         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
647     }
648 #endif
649
650
651 #if 0
652     if(sym->iaccess) {
653       if(space->paged) {
654         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
655
656         sym->aop = aop = newAsmop (AOP_PAGED);
657         aop->aopu.aop_dir = sym->rname ;
658         aop->size = getSize(sym->type);
659         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660         pic16_allocDirReg( IC_LEFT(ic) );
661         return aop;
662       }
663       assert( 0 );
664     }
665 #endif
666     
667 #if 1
668     /* assign depending on the storage class */
669     /* if it is on the stack or indirectly addressable */
670     /* space we need to assign either r0 or r1 to it   */    
671     if (sym->onStack)   // || sym->iaccess)
672     {
673       pCodeOp *pcop[4];
674       int i;
675       
676         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
677                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
678         
679         /* acquire a temporary register -- it is saved in function */
680
681         sym->aop = aop = newAsmop(AOP_STA);
682         aop->aopu.stk.stk = sym->stack;
683         aop->size = getSize(sym->type);
684
685
686         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
687         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
688           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
689           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
690           
691           for(i=0;i<aop->size;i++)
692             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
693             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
694         } else
695           for(i=0;i<aop->size;i++) {
696             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
697             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
698           }
699
700
701 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
702
703 #if 1
704         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
705
706         // we do not need to load the value if it is to be defined...
707         if (result) return aop;
708
709         if(_G.accInUse) {
710                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
711         }
712         
713         for(i=0;i<aop->size;i++) {
714
715           /* initialise for stack access via frame pointer */
716           // operands on stack are accessible via "FSR2 + index" with index
717           // starting at 2 for arguments and growing from 0 downwards for
718           // local variables (index == 0 is not assigned so we add one here)
719           {
720             int soffs = sym->stack;
721             if (soffs <= 0) {
722               assert (soffs < 0);
723               soffs++;
724             } // if
725             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
726             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
727                             pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
728           }
729         }
730         
731         if(_G.accInUse) {
732                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
733         }
734         
735         return (aop);
736 #endif
737
738 #if 0
739         /* now assign the address of the variable to 
740         the pointer register */
741         if (aop->type != AOP_STK) {
742
743             if (sym->onStack) {
744                     if ( _G.accInUse )
745                         pic16_emitcode("push","acc");
746
747                     pic16_emitcode("mov","a,_bp");
748                     pic16_emitcode("add","a,#0x%02x",
749                              ((sym->stack < 0) ?
750                               ((char)(sym->stack - _G.nRegsSaved )) :
751                               ((char)sym->stack)) & 0xff);
752                     pic16_emitcode("mov","%s,a",
753                              aop->aopu.aop_ptr->name);
754
755                     if ( _G.accInUse )
756                         pic16_emitcode("pop","acc");
757             } else
758                 pic16_emitcode("mov","%s,#%s",
759                          aop->aopu.aop_ptr->name,
760                          sym->rname);
761             aop->paged = space->paged;
762         } else
763             aop->aopu.aop_stk = sym->stack;
764         return aop;
765 #endif
766
767     }
768 #endif
769
770 #if 0
771     if (sym->onStack && options.stack10bit)
772     {
773         /* It's on the 10 bit stack, which is located in
774          * far data space.
775          */
776          
777       //DEBUGpic16_emitcode(";","%d",__LINE__);
778
779         if ( _G.accInUse )
780                 pic16_emitcode("push","acc");
781
782         pic16_emitcode("mov","a,_bp");
783         pic16_emitcode("add","a,#0x%02x",
784                  ((sym->stack < 0) ?
785                    ((char)(sym->stack - _G.nRegsSaved )) :
786                    ((char)sym->stack)) & 0xff);
787         
788         genSetDPTR(1);
789         pic16_emitcode ("mov","dpx1,#0x40");
790         pic16_emitcode ("mov","dph1,#0x00");
791         pic16_emitcode ("mov","dpl1, a");
792         genSetDPTR(0);
793         
794         if ( _G.accInUse )
795             pic16_emitcode("pop","acc");
796             
797         sym->aop = aop = newAsmop(AOP_DPTR2);
798         aop->size = getSize(sym->type); 
799         return aop;
800     }
801 #endif
802
803 #if 1
804     /* special case for a function */
805     if (IS_FUNC(sym->type)) {   
806         sym->aop = aop = newAsmop(AOP_PCODE);
807         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
808         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
809         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
810         PCOI(aop->aopu.pcop)->index = 0;
811         aop->size = FPTRSIZE; 
812         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
813         return aop;
814     }
815 #endif
816
817
818
819     //DEBUGpic16_emitcode(";","%d",__LINE__);
820     /* if in bit space */
821     if (IN_BITSPACE(space)) {
822         sym->aop = aop = newAsmop (AOP_CRY);
823         aop->aopu.aop_dir = sym->rname ;
824         aop->size = getSize(sym->type);
825         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
826         return aop;
827     }
828     /* if it is in direct space */
829     if (IN_DIRSPACE(space)) {
830         sym->aop = aop = newAsmop (AOP_DIR);
831         aop->aopu.aop_dir = sym->rname ;
832         aop->size = getSize(sym->type);
833         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
834         pic16_allocDirReg( IC_LEFT(ic) );
835         return aop;
836     }
837
838
839     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
840         sym->aop = aop = newAsmop (AOP_DIR);
841         aop->aopu.aop_dir = sym->rname ;
842         aop->size = getSize(sym->type);
843         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
844         pic16_allocDirReg( IC_LEFT(ic) );
845         return aop;
846     }
847
848
849     /* only remaining is far space */
850     sym->aop = aop = newAsmop(AOP_PCODE);
851
852 /* change the next if to 1 to revert to good old immediate code */
853         if(IN_CODESPACE(space)) {
854                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
855                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
856                 PCOI(aop->aopu.pcop)->index = 0;
857         } else {
858                 /* try to allocate via direct register */
859                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
860 //              aop->size = getSize( sym->type );
861         }
862
863         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
864                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
865
866 #if 0
867         if(!pic16_allocDirReg (IC_LEFT(ic)))
868                 return NULL;
869 #endif
870
871         if(IN_DIRSPACE( space ))
872                 aop->size = PTRSIZE;
873         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
874                 aop->size = FPTRSIZE;
875         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
876         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
877         else if(sym->onStack) {
878                 aop->size = PTRSIZE;
879         } else {
880           if(SPEC_SCLS(sym->etype) == S_PDATA) {
881             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
882             aop->size = FPTRSIZE;
883           } else
884                 assert( 0 );
885         }
886
887     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
888
889     /* if it is in code space */
890     if (IN_CODESPACE(space))
891         aop->code = 1;
892
893     return aop;     
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* aopForRemat - rematerialzes an object                           */
898 /*-----------------------------------------------------------------*/
899 static asmop *aopForRemat (operand *op) // x symbol *sym)
900 {
901   symbol *sym = OP_SYMBOL(op);
902   operand *refop;
903   iCode *ic = NULL, *oldic;
904   asmop *aop = newAsmop(AOP_PCODE);
905   int val = 0;
906   int offset = 0;
907   int viaimmd=0;
908
909     FENTRY2;
910     
911         ic = sym->rematiCode;
912
913         if(IS_OP_POINTER(op)) {
914                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
915         }
916
917         for (;;) {
918                 oldic = ic;
919
920 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
921         
922                 if (ic->op == '+') {
923                         val += (int) operandLitValue(IC_RIGHT(ic));
924                 } else if (ic->op == '-') {
925                         val -= (int) operandLitValue(IC_RIGHT(ic));
926                 } else
927                         break;
928                 
929                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
930         }
931
932         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
933         refop = IC_LEFT(ic);
934
935         if(!op->isaddr)viaimmd++; else viaimmd=0;
936                 
937 /* set the following if to 1 to revert to good old immediate code */
938         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
939                 || viaimmd) {
940
941                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
942
943                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
944
945 #if 0
946                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
947 #else
948                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
949 #endif
950
951                 PCOI(aop->aopu.pcop)->index = val;
952                 
953                 aop->size = getSize( sym->type );
954         } else {
955                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
956
957                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
958                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
959
960                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
961         }
962
963
964         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
965                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
966 #if 0
967                 val, IS_PTR_CONST(operandType(op)));
968 #else
969                 val, IS_CODEPTR(operandType(op)));
970 #endif
971
972 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
973
974         pic16_allocDirReg (IC_LEFT(ic));
975
976         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
977                 aop->code = 1;
978
979   return aop;        
980 }
981
982 #if 0
983 static int aopIdx (asmop *aop, int offset)
984 {
985   if(!aop)
986     return -1;
987
988   if(aop->type !=  AOP_REG)
989     return -2;
990         
991   return aop->aopu.aop_reg[offset]->rIdx;
992
993 }
994 #endif
995
996 /*-----------------------------------------------------------------*/
997 /* regsInCommon - two operands have some registers in common       */
998 /*-----------------------------------------------------------------*/
999 static bool regsInCommon (operand *op1, operand *op2)
1000 {
1001     symbol *sym1, *sym2;
1002     int i;
1003
1004     /* if they have registers in common */
1005     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1006         return FALSE ;
1007
1008     sym1 = OP_SYMBOL(op1);
1009     sym2 = OP_SYMBOL(op2);
1010
1011     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1012         return FALSE ;
1013
1014     for (i = 0 ; i < sym1->nRegs ; i++) {
1015         int j;
1016         if (!sym1->regs[i])
1017             continue ;
1018
1019         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1020             if (!sym2->regs[j])
1021                 continue ;
1022
1023             if (sym2->regs[j] == sym1->regs[i])
1024                 return TRUE ;
1025         }
1026     }
1027
1028     return FALSE ;
1029 }
1030
1031 /*-----------------------------------------------------------------*/
1032 /* operandsEqu - equivalent                                        */
1033 /*-----------------------------------------------------------------*/
1034 static bool operandsEqu ( operand *op1, operand *op2)
1035 {
1036     symbol *sym1, *sym2;
1037
1038     /* if they not symbols */
1039     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1040         return FALSE;
1041
1042     sym1 = OP_SYMBOL(op1);
1043     sym2 = OP_SYMBOL(op2);
1044
1045     /* if both are itemps & one is spilt
1046        and the other is not then false */
1047     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1048         sym1->isspilt != sym2->isspilt )
1049         return FALSE ;
1050
1051     /* if they are the same */
1052     if (sym1 == sym2)
1053         return TRUE ;
1054
1055     if (sym1->rname[0] && sym2->rname[0]
1056         && strcmp (sym1->rname, sym2->rname) == 0)
1057         return TRUE;
1058
1059
1060     /* if left is a tmp & right is not */
1061     if (IS_ITEMP(op1)  && 
1062         !IS_ITEMP(op2) &&
1063         sym1->isspilt  &&
1064         (sym1->usl.spillLoc == sym2))
1065         return TRUE;
1066
1067     if (IS_ITEMP(op2)  && 
1068         !IS_ITEMP(op1) &&
1069         sym2->isspilt  &&
1070         sym1->level > 0 &&
1071         (sym2->usl.spillLoc == sym1))
1072         return TRUE ;
1073
1074     return FALSE ;
1075 }
1076
1077 /*-----------------------------------------------------------------*/
1078 /* pic16_sameRegs - two asmops have the same registers                   */
1079 /*-----------------------------------------------------------------*/
1080 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1081 {
1082     int i;
1083
1084     if (aop1 == aop2)
1085         return TRUE ;
1086
1087     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1088                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1089
1090     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1091
1092     if (aop1->type != AOP_REG ||
1093         aop2->type != AOP_REG )
1094         return FALSE ;
1095
1096     /* This is a bit too restrictive if one is a subset of the other...
1097     if (aop1->size != aop2->size )
1098         return FALSE ;
1099     */
1100
1101     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1102 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1103
1104 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1105         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1106             return FALSE ;
1107     }
1108
1109     return TRUE ;
1110 }
1111
1112 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1113 {
1114     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1115                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1116
1117     if(aop1 == aop2)return TRUE;
1118     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1119       
1120       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1121     
1122   return TRUE;
1123 }
1124
1125
1126 /*-----------------------------------------------------------------*/
1127 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1128 /*-----------------------------------------------------------------*/
1129 void pic16_aopOp (operand *op, iCode *ic, bool result)
1130 {
1131     asmop *aop;
1132     symbol *sym;
1133     int i;
1134
1135     if (!op)
1136         return ;
1137
1138     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1139
1140     /* if this a literal */
1141     if (IS_OP_LITERAL(op)) {
1142         op->aop = aop = newAsmop(AOP_LIT);
1143         aop->aopu.aop_lit = op->operand.valOperand;
1144         aop->size = getSize(operandType(op));
1145         return;
1146     }
1147
1148     {
1149       sym_link *type = operandType(op);
1150 #if 0
1151       if(IS_PTR_CONST(type))
1152 #else
1153       if(IS_CODEPTR(type))
1154 #endif
1155         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1156     }
1157
1158     /* if already has a asmop then continue */
1159     if (op->aop)
1160         return ;
1161
1162     /* if the underlying symbol has a aop */
1163     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1164       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1165         op->aop = OP_SYMBOL(op)->aop;
1166         return;
1167     }
1168
1169     /* if this is a true symbol */
1170     if (IS_TRUE_SYMOP(op)) {    
1171         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1172       op->aop = aopForSym(ic, op, result);
1173       return ;
1174     }
1175
1176     /* this is a temporary : this has
1177     only four choices :
1178     a) register
1179     b) spillocation
1180     c) rematerialize 
1181     d) conditional   
1182     e) can be a return use only */
1183
1184     sym = OP_SYMBOL(op);
1185
1186     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1187     /* if the type is a conditional */
1188     if (sym->regType == REG_CND) {
1189         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1190         aop->size = 0;
1191         return;
1192     }
1193
1194     /* if it is spilt then two situations
1195     a) is rematerialize 
1196     b) has a spill location */
1197     if (sym->isspilt || sym->nRegs == 0) {
1198
1199 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1200       DEBUGpic16_emitcode(";","%d",__LINE__);
1201         /* rematerialize it NOW */
1202         if (sym->remat) {
1203
1204             sym->aop = op->aop = aop = aopForRemat (op);
1205 //            aop->size = getSize(sym->type);
1206 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1207             return;
1208         }
1209
1210 #if 1
1211         if (sym->accuse) {
1212             int i;
1213             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1214             aop->size = getSize(sym->type);
1215             for ( i = 0 ; i < 1 ; i++ ) {
1216                 aop->aopu.aop_str[i] = accUse[i];
1217 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1218             }
1219             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1220             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1221             return;  
1222         }
1223 #endif
1224
1225 #if 1
1226         if (sym->ruonly) {
1227           /*
1228           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1229           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1230           //pic16_allocDirReg (IC_LEFT(ic));
1231           aop->size = getSize(sym->type);
1232           */
1233
1234           unsigned i;
1235
1236           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1237           aop->size = getSize(sym->type);
1238           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1239             aop->aopu.aop_str[i] = fReturn[i];
1240
1241           DEBUGpic16_emitcode(";","%d",__LINE__);
1242           return;
1243         }
1244 #endif
1245         /* else spill location  */
1246         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1247             /* force a new aop if sizes differ */
1248             sym->usl.spillLoc->aop = NULL;
1249         }
1250
1251 #if 0
1252         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1253                             __FUNCTION__,__LINE__,
1254                             sym->usl.spillLoc->rname,
1255                             sym->rname, sym->usl.spillLoc->offset);
1256 #endif
1257
1258         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1259         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1260         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1261           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1262                                                   getSize(sym->type), 
1263                                                   sym->usl.spillLoc->offset, op);
1264         } else {
1265           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1266           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1267           assert (getSize(sym->type) <= 1);
1268           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1269         }
1270         aop->size = getSize(sym->type);
1271
1272         return;
1273     }
1274
1275     {
1276       sym_link *type = operandType(op);
1277 #if 0
1278       if(IS_PTR_CONST(type)) 
1279 #else
1280       if(IS_CODEPTR(type)) 
1281 #endif
1282         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1283     }
1284
1285     /* must be in a register */
1286     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1287     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1288     aop->size = sym->nRegs;
1289     for ( i = 0 ; i < sym->nRegs ;i++)
1290         aop->aopu.aop_reg[i] = sym->regs[i];
1291 }
1292
1293 /*-----------------------------------------------------------------*/
1294 /* pic16_freeAsmop - free up the asmop given to an operand               */
1295 /*----------------------------------------------------------------*/
1296 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1297 {   
1298     asmop *aop ;
1299
1300     if (!op)
1301         aop = aaop;
1302     else 
1303         aop = op->aop;
1304
1305     if (!aop)
1306         return ;
1307
1308     if (aop->freed)
1309         goto dealloc; 
1310
1311     aop->freed = 1;
1312
1313     /* depending on the asmop type only three cases need work AOP_RO
1314        , AOP_R1 && AOP_STK */
1315 #if 1
1316     switch (aop->type) {
1317         case AOP_FSR0 :
1318             if (_G.fsr0Pushed ) {
1319                 if (pop) {
1320                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1321                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1322 //                    pic16_emitcode ("pop","ar0");
1323                     _G.fsr0Pushed--;
1324                 }
1325             }
1326             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1327             break;
1328
1329         case AOP_FSR2 :
1330             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1331             break;
1332
1333         case AOP_R0 :
1334             if (_G.r0Pushed ) {
1335                 if (pop) {
1336                     pic16_emitcode ("pop","ar0");     
1337                     _G.r0Pushed--;
1338                 }
1339             }
1340             bitVectUnSetBit(ic->rUsed,R0_IDX);
1341             break;
1342
1343         case AOP_R1 :
1344             if (_G.r1Pushed ) {
1345                 if (pop) {
1346                     pic16_emitcode ("pop","ar1");
1347                     _G.r1Pushed--;
1348                 }
1349             }
1350             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1351             break;
1352
1353         case AOP_STA:
1354           {
1355             int i;
1356
1357               /* we must store the result on stack */
1358               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1359                 // operands on stack are accessible via "FSR2 + index" with index
1360                 // starting at 2 for arguments and growing from 0 downwards for
1361                 // local variables (index == 0 is not assigned so we add one here)
1362                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1363                 if (soffs <= 0) {
1364                   assert (soffs < 0);
1365                   soffs++;
1366                 } // if
1367                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1368                 for(i=0;i<aop->size;i++) {
1369                   /* initialise for stack access via frame pointer */
1370                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1371                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1372                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1373                 }
1374         
1375                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1376               }
1377
1378               if(!_G.resDirect) {
1379                 for(i=0;i<aop->size;i++)
1380                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1381               }
1382               _G.resDirect = 0;
1383           }
1384           break;
1385 #if 0
1386         case AOP_STK :
1387         {
1388             int sz = aop->size;    
1389             int stk = aop->aopu.aop_stk + aop->size;
1390             bitVectUnSetBit(ic->rUsed,R0_IDX);
1391             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1392
1393             getFreePtr(ic,&aop,FALSE);
1394             
1395             if (options.stack10bit)
1396             {
1397                 /* I'm not sure what to do here yet... */
1398                 /* #STUB */
1399                 fprintf(stderr, 
1400                         "*** Warning: probably generating bad code for "
1401                         "10 bit stack mode.\n");
1402             }
1403             
1404             if (stk) {
1405                 pic16_emitcode ("mov","a,_bp");
1406                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1407                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1408             } else {
1409                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1410             }
1411
1412             while (sz--) {
1413                 pic16_emitcode("pop","acc");
1414                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1415                 if (!sz) break;
1416                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1417             }
1418             op->aop = aop;
1419             pic16_freeAsmop(op,NULL,ic,TRUE);
1420             if (_G.r0Pushed) {
1421                 pic16_emitcode("pop","ar0");
1422                 _G.r0Pushed--;
1423             }
1424
1425             if (_G.r1Pushed) {
1426                 pic16_emitcode("pop","ar1");
1427                 _G.r1Pushed--;
1428             }       
1429         }
1430 #endif
1431
1432     }
1433 #endif
1434
1435 dealloc:
1436     /* all other cases just dealloc */
1437     if (op ) {
1438         op->aop = NULL;
1439         if (IS_SYMOP(op)) {
1440             OP_SYMBOL(op)->aop = NULL;    
1441             /* if the symbol has a spill */
1442             if (SPIL_LOC(op))
1443                 SPIL_LOC(op)->aop = NULL;
1444         }
1445     }
1446 }
1447
1448 /*-----------------------------------------------------------------*/
1449 /* pic16_aopGet - for fetching value of the aop                          */
1450 /*-----------------------------------------------------------------*/
1451 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1452 {
1453     char *s = buffer ;
1454     char *rs;
1455
1456     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1457
1458     /* offset is greater than size then zero */
1459     if (offset > (aop->size - 1) &&
1460         aop->type != AOP_LIT)
1461         return zero;
1462
1463     /* depending on type */
1464     switch (aop->type) {
1465
1466     case AOP_FSR0:
1467     case AOP_FSR2:
1468       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1469       rs = Safe_calloc(1, strlen(s)+1);
1470       strcpy(rs, s);
1471       return (rs);
1472       
1473 #if 0
1474       /* if we need to increment it */
1475       while (offset > aop->coff)
1476         {
1477           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478           aop->coff++;
1479         }
1480
1481       while (offset < aop->coff)
1482         {
1483           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1484           aop->coff--;
1485         }
1486       aop->coff = offset;
1487       if (aop->paged)
1488         {
1489           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1490           return (dname ? "acc" : "a");
1491         }
1492       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1493       rs = Safe_calloc (1, strlen (s) + 1);
1494       strcpy (rs, s);
1495       return rs;
1496 #endif
1497
1498         
1499     case AOP_IMMD:
1500         if (bit16) 
1501             sprintf (s,"%s",aop->aopu.aop_immd);
1502         else
1503             if (offset) 
1504                 sprintf(s,"(%s >> %d)",
1505                         aop->aopu.aop_immd,
1506                         offset*8);
1507             else
1508                 sprintf(s,"%s",
1509                         aop->aopu.aop_immd);
1510         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1511         rs = Safe_calloc(1,strlen(s)+1);
1512         strcpy(rs,s);   
1513         return rs;
1514         
1515     case AOP_DIR:
1516       if (offset) {
1517         sprintf(s,"(%s + %d)",
1518                 aop->aopu.aop_dir,
1519                 offset);
1520         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1521       } else
1522             sprintf(s,"%s",aop->aopu.aop_dir);
1523         rs = Safe_calloc(1,strlen(s)+1);
1524         strcpy(rs,s);   
1525         return rs;
1526         
1527     case AOP_REG:
1528       //if (dname) 
1529       //    return aop->aopu.aop_reg[offset]->dname;
1530       //else
1531             return aop->aopu.aop_reg[offset]->name;
1532         
1533     case AOP_CRY:
1534       //pic16_emitcode(";","%d",__LINE__);
1535       return aop->aopu.aop_dir;
1536         
1537     case AOP_ACC:
1538         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1539 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1540 //        assert( 0 );
1541 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1542         rs = Safe_strdup("WREG");
1543         return (rs);
1544
1545     case AOP_LIT:
1546         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1547         rs = Safe_calloc(1,strlen(s)+1);
1548         strcpy(rs,s);   
1549         return rs;
1550         
1551     case AOP_STR:
1552         aop->coff = offset ;
1553         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1554             dname)
1555             return "acc";
1556         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1557         
1558         return aop->aopu.aop_str[offset];
1559         
1560     case AOP_PCODE:
1561       {
1562         pCodeOp *pcop = aop->aopu.pcop;
1563         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1564         if(pcop->name) {
1565           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1566           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1567           if (offset) {
1568             sprintf(s,"(%s + %d)", pcop->name, offset);
1569           } else {
1570             sprintf(s,"%s", pcop->name);
1571           }
1572         } else
1573           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1574
1575       }
1576       rs = Safe_calloc(1,strlen(s)+1);
1577       strcpy(rs,s);   
1578       return rs;
1579
1580 #if 0
1581     case AOP_PAGED:
1582       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1583       if (offset) {
1584         sprintf(s,"(%s + %d)",
1585                 aop->aopu.aop_dir,
1586                 offset);
1587       } else
1588             sprintf(s,"%s",aop->aopu.aop_dir);
1589       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1590       rs = Safe_calloc(1,strlen(s)+1);
1591       strcpy(rs,s);   
1592       return rs;
1593 #endif
1594
1595     case AOP_STA:
1596         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1597         return (rs);
1598         
1599     case AOP_STK:
1600 //        pCodeOp *pcop = aop->aop
1601         break;
1602
1603     }
1604
1605     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1606     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1607            "aopget got unsupported aop->type");
1608     exit(0);
1609 }
1610
1611
1612
1613 /* lock has the following meaning: When allocating temporary registers
1614  * for stack variables storage, the value of the temporary register is
1615  * saved on stack. Its value is restored at the end. This procedure is
1616  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1617  * a possibility that before a call to pic16_aopOp, a temporary register
1618  * is allocated for a while and it is freed after some time, this will
1619  * mess the stack and values will not be restored properly. So use lock=1
1620  * to allocate temporary registers used internally by the programmer, and
1621  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1622  * to inform the compiler developer about a possible bug. This is an internal
1623  * feature for developing the compiler -- VR */
1624  
1625 int _TempReg_lock = 0;
1626 /*-----------------------------------------------------------------*/
1627 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1628 /*-----------------------------------------------------------------*/
1629 pCodeOp *pic16_popGetTempReg(int lock)
1630 {
1631   pCodeOp *pcop;
1632   symbol *cfunc;
1633
1634 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1635     if(_TempReg_lock) {
1636 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1637     }
1638     
1639     _TempReg_lock += lock;
1640     
1641     cfunc = currFunc;
1642     currFunc = NULL;
1643
1644     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1645     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1646       PCOR(pcop)->r->wasUsed=1;
1647       PCOR(pcop)->r->isFree=0;
1648
1649       /* push value on stack */
1650       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1651     }
1652
1653     currFunc = cfunc;
1654
1655   return pcop;
1656 }
1657
1658 /*-----------------------------------------------------------------*/
1659 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1660 /*                            don't save if inside v               */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1663 {
1664   pCodeOp *pcop;
1665   symbol *cfunc;
1666
1667 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1668
1669     if(_TempReg_lock) {
1670 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1671     }
1672
1673     _TempReg_lock += lock;
1674
1675     cfunc = currFunc;
1676     currFunc = NULL;
1677
1678     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1679     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1680       PCOR(pcop)->r->wasUsed=1;
1681       PCOR(pcop)->r->isFree=0;
1682
1683       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1684       /* push value on stack */
1685         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1686       }
1687     }
1688
1689     currFunc = cfunc;
1690
1691   return pcop;
1692 }
1693
1694
1695 /*-----------------------------------------------------------------*/
1696 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1697 /*-----------------------------------------------------------------*/
1698 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1699 {
1700   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1701
1702   _TempReg_lock -= lock;
1703
1704   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1705     PCOR(pcop)->r->isFree = 1;
1706     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1707   }
1708 }
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1711 /*-----------------------------------------------------------------*/
1712 pCodeOp *pic16_popGetLabel(unsigned int key)
1713 {
1714
1715   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1716
1717   if(key>max_key)
1718     max_key = key;
1719
1720   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1721 }
1722
1723 /*-----------------------------------------------------------------*/
1724 /* pic16_popCopyReg - copy a pcode operator                              */
1725 /*-----------------------------------------------------------------*/
1726 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1727 {
1728   pCodeOpReg *pcor;
1729
1730   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1731   pcor->pcop.type = pc->pcop.type;
1732   if(pc->pcop.name) {
1733     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1734       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1735   } else
1736     pcor->pcop.name = NULL;
1737
1738   pcor->r = pc->r;
1739   pcor->rIdx = pc->rIdx;
1740   pcor->r->wasUsed=1;
1741   pcor->instance = pc->instance;
1742
1743 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1744
1745   return PCOP(pcor);
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1750 /*-----------------------------------------------------------------*/
1751 pCodeOp *pic16_popGetLit(int lit)
1752 {
1753   return pic16_newpCodeOpLit(lit);
1754 }
1755
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1758 /*-----------------------------------------------------------------*/
1759 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1760 {
1761   return pic16_newpCodeOpLit2(lit, arg2);
1762 }
1763
1764
1765 /*-----------------------------------------------------------------*/
1766 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1769 {
1770   return pic16_newpCodeOpImmd(name, offset,index, 0);
1771 }
1772
1773
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGet - asm operator to pcode operator conversion              */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetWithString(char *str)
1778 {
1779   pCodeOp *pcop;
1780
1781
1782   if(!str) {
1783     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1784     exit (1);
1785   }
1786
1787   pcop = pic16_newpCodeOp(str,PO_STR);
1788
1789   return pcop;
1790 }
1791
1792 /*-----------------------------------------------------------------*/
1793 /* pic16_popRegFromString -                                        */
1794 /*-----------------------------------------------------------------*/
1795 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1796 {
1797
1798   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1799   pcop->type = PO_DIR;
1800
1801   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1802   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1803
1804   if(!str)
1805     str = "BAD_STRING";
1806
1807   pcop->name = Safe_calloc(1,strlen(str)+1);
1808   strcpy(pcop->name,str);
1809
1810   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1811
1812   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1813
1814   /* make sure that register doesn't exist,
1815    * and operand isn't NULL
1816    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1817   if((PCOR(pcop)->r == NULL) 
1818     && (op)
1819     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1820 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1821 //              __FUNCTION__, __LINE__, str, size, offset);
1822
1823     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1824     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1825
1826   }
1827   PCOR(pcop)->instance = offset;
1828
1829   return pcop;
1830 }
1831
1832 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1833 {
1834   pCodeOp *pcop;
1835
1836 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1837
1838         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1839         PCOR(pcop)->rIdx = rIdx;
1840         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1841
1842         PCOR(pcop)->r->isFree = 0;
1843         PCOR(pcop)->r->wasUsed = 1;
1844
1845         pcop->type = PCOR(pcop)->r->pc_type;
1846
1847   return pcop;
1848 }
1849
1850 /*---------------------------------------------------------------------------------*/
1851 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1852 /*                 VR 030601                                                       */
1853 /*---------------------------------------------------------------------------------*/
1854 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1855 {
1856   pCodeOpReg2 *pcop2;
1857   pCodeOp *temp;
1858   
1859         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1860
1861         /* comment the following check, so errors to throw up */
1862 //      if(!pcop2)return NULL;
1863
1864         temp = pic16_popGet(aop_dst, offset);
1865         pcop2->pcop2 = temp;
1866         
1867   return PCOP(pcop2);
1868 }
1869
1870
1871
1872 /*--------------------------------------------------------------------------------.-*/
1873 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1874 /*                  VR 030601 , adapted by Hans Dorn                                */
1875 /*--------------------------------------------------------------------------------.-*/
1876 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1877 {
1878   pCodeOpReg2 *pcop2;
1879  
1880         pcop2 = (pCodeOpReg2 *)src;
1881         pcop2->pcop2 = dst;
1882         
1883         return PCOP(pcop2);
1884 }
1885
1886
1887
1888 /*---------------------------------------------------------------------------------*/
1889 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1890 /*                     movff instruction                                           */
1891 /*---------------------------------------------------------------------------------*/
1892 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1893 {
1894   pCodeOpReg2 *pcop2;
1895
1896         if(!noalloc) {
1897                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1898                 pcop2->pcop2 = pic16_popCopyReg(dst);
1899         } else {
1900                 /* the pCodeOp may be already allocated */
1901                 pcop2 = (pCodeOpReg2 *)(src);
1902                 pcop2->pcop2 = (pCodeOp *)(dst);
1903         }
1904
1905   return PCOP(pcop2);
1906 }
1907
1908
1909 /*-----------------------------------------------------------------*/
1910 /* pic16_popGet - asm operator to pcode operator conversion              */
1911 /*-----------------------------------------------------------------*/
1912 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1913 {
1914   //char *s = buffer ;
1915   char *rs;
1916   pCodeOp *pcop;
1917
1918     FENTRY2;
1919     /* offset is greater than
1920     size then zero */
1921
1922 //    if (offset > (aop->size - 1) &&
1923 //        aop->type != AOP_LIT)
1924 //      return NULL;  //zero;
1925
1926     /* depending on type */
1927     switch (aop->type) {
1928         
1929     case AOP_R0:
1930     case AOP_R1:
1931     case AOP_DPTR:
1932     case AOP_DPTR2:
1933         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1934         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1935         assert( 0 );
1936         return NULL;
1937
1938
1939     case AOP_FSR0:
1940     case AOP_FSR2:
1941       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1942       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1943       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1944       PCOR(pcop)->r->wasUsed = 1;
1945       PCOR(pcop)->r->isFree = 0;
1946       
1947       PCOR(pcop)->instance = offset;
1948       pcop->type = PCOR(pcop)->r->pc_type;
1949       return (pcop);
1950
1951     case AOP_IMMD:
1952       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1953       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1954
1955     case AOP_STA:
1956       /* pCodeOp is already allocated from aopForSym */
1957         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1958         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1959           
1960       return (pcop);
1961       
1962     case AOP_ACC:
1963       {
1964         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1965
1966         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1967
1968         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1969         
1970         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1971         PCOR(pcop)->rIdx = rIdx;
1972         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1973         PCOR(pcop)->r->wasUsed=1;
1974         PCOR(pcop)->r->isFree=0;
1975
1976         PCOR(pcop)->instance = offset;
1977         pcop->type = PCOR(pcop)->r->pc_type;
1978 //      rs = aop->aopu.aop_reg[offset]->name;
1979 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1980         return pcop;
1981
1982
1983 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1984 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1985
1986 //      assert( 0 );
1987       }
1988         
1989     case AOP_DIR:
1990       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1991       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1992         
1993 #if 0
1994     case AOP_PAGED:
1995       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1996       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1997 #endif
1998
1999     case AOP_REG:
2000       {
2001         int rIdx;
2002         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2003         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2004
2005         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2006         
2007         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2008 //      pcop->type = PO_GPR_REGISTER;
2009         PCOR(pcop)->rIdx = rIdx;
2010         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2011         PCOR(pcop)->r->wasUsed=1;
2012         PCOR(pcop)->r->isFree=0;
2013
2014         PCOR(pcop)->instance = offset;
2015         pcop->type = PCOR(pcop)->r->pc_type;
2016         
2017         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2018         rs = aop->aopu.aop_reg[offset]->name;
2019         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2020         return pcop;
2021       }
2022
2023     case AOP_CRY:
2024         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2025
2026       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2027       PCOR(pcop)->instance = offset;
2028       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2029       //if(PCOR(pcop)->r == NULL)
2030       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2031       return pcop;
2032         
2033     case AOP_LIT:
2034         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2035       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2036
2037     case AOP_STR:
2038       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2039       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2040
2041       /*
2042       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2043       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2044       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2045       pcop->type = PCOR(pcop)->r->pc_type;
2046       pcop->name = PCOR(pcop)->r->name;
2047
2048       return pcop;
2049       */
2050
2051     case AOP_PCODE:
2052       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2053                           __LINE__, 
2054                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2055       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2056       switch( aop->aopu.pcop->type ) {
2057         case PO_DIR: PCOR(pcop)->instance += offset; break;
2058         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2059         case PO_WREG:
2060             assert (offset==0);
2061             break;
2062         default:
2063           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2064           assert( 0 );  /* should never reach here */;
2065       }
2066       return pcop;
2067     }
2068
2069     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2070            "pic16_popGet got unsupported aop->type");
2071     exit(0);
2072 }
2073 /*-----------------------------------------------------------------*/
2074 /* pic16_aopPut - puts a string for a aop                                */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_aopPut (asmop *aop, char *s, int offset)
2077 {
2078     char *d = buffer ;
2079     symbol *lbl ;
2080
2081     return;
2082
2083     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2084
2085     if (aop->size && offset > ( aop->size - 1)) {
2086         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2087                "pic16_aopPut got offset > aop->size");
2088         exit(0);
2089     }
2090
2091     /* will assign value to value */
2092     /* depending on where it is ofcourse */
2093     switch (aop->type) {
2094     case AOP_DIR:
2095       if (offset) {
2096         sprintf(d,"(%s + %d)",
2097                 aop->aopu.aop_dir,offset);
2098         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2099
2100       } else
2101             sprintf(d,"%s",aop->aopu.aop_dir);
2102         
2103         if (strcmp(d,s)) {
2104           DEBUGpic16_emitcode(";","%d",__LINE__);
2105           if(strcmp(s,"W"))
2106             pic16_emitcode("movf","%s,w",s);
2107           pic16_emitcode("movwf","%s",d);
2108
2109           if(strcmp(s,"W")) {
2110             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2111             if(offset >= aop->size) {
2112               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2113               break;
2114             } else
2115               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2116           }
2117
2118           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2119
2120
2121         }
2122         break;
2123         
2124     case AOP_REG:
2125       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2126         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2127           /*
2128             if (*s == '@'           ||
2129                 strcmp(s,"r0") == 0 ||
2130                 strcmp(s,"r1") == 0 ||
2131                 strcmp(s,"r2") == 0 ||
2132                 strcmp(s,"r3") == 0 ||
2133                 strcmp(s,"r4") == 0 ||
2134                 strcmp(s,"r5") == 0 ||
2135                 strcmp(s,"r6") == 0 || 
2136                 strcmp(s,"r7") == 0 )
2137                 pic16_emitcode("mov","%s,%s  ; %d",
2138                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2139             else
2140           */
2141
2142           if(strcmp(s,"W")==0 )
2143             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2144
2145           pic16_emitcode("movwf","%s",
2146                    aop->aopu.aop_reg[offset]->name);
2147
2148           if(strcmp(s,zero)==0) {
2149             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2150
2151           } else if(strcmp(s,"W")==0) {
2152             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2153             pcop->type = PO_GPR_REGISTER;
2154
2155             PCOR(pcop)->rIdx = -1;
2156             PCOR(pcop)->r = NULL;
2157
2158             DEBUGpic16_emitcode(";","%d",__LINE__);
2159             pcop->name = Safe_strdup(s);
2160             pic16_emitpcode(POC_MOVFW,pcop);
2161             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2162           } else if(strcmp(s,one)==0) {
2163             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2164             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2165           } else {
2166             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2167           }
2168         }
2169         break;
2170         
2171     case AOP_DPTR:
2172     case AOP_DPTR2:
2173     
2174     if (aop->type == AOP_DPTR2)
2175     {
2176         genSetDPTR(1);
2177     }
2178     
2179         if (aop->code) {
2180             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2181                    "pic16_aopPut writting to code space");
2182             exit(0);
2183         }
2184         
2185         while (offset > aop->coff) {
2186             aop->coff++;
2187             pic16_emitcode ("inc","dptr");
2188         }
2189         
2190         while (offset < aop->coff) {
2191             aop->coff-- ;
2192             pic16_emitcode("lcall","__decdptr");
2193         }
2194         
2195         aop->coff = offset;
2196         
2197         /* if not in accumulater */
2198         MOVA(s);        
2199         
2200         pic16_emitcode ("movx","@dptr,a");
2201         
2202     if (aop->type == AOP_DPTR2)
2203     {
2204         genSetDPTR(0);
2205     }
2206         break;
2207         
2208     case AOP_R0:
2209     case AOP_R1:
2210         while (offset > aop->coff) {
2211             aop->coff++;
2212             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2213         }
2214         while (offset < aop->coff) {
2215             aop->coff-- ;
2216             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2217         }
2218         aop->coff = offset;
2219         
2220         if (aop->paged) {
2221             MOVA(s);           
2222             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2223             
2224         } else
2225             if (*s == '@') {
2226                 MOVA(s);
2227                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2228             } else
2229                 if (strcmp(s,"r0") == 0 ||
2230                     strcmp(s,"r1") == 0 ||
2231                     strcmp(s,"r2") == 0 ||
2232                     strcmp(s,"r3") == 0 ||
2233                     strcmp(s,"r4") == 0 ||
2234                     strcmp(s,"r5") == 0 ||
2235                     strcmp(s,"r6") == 0 || 
2236                     strcmp(s,"r7") == 0 ) {
2237                     char buffer[10];
2238                     sprintf(buffer,"a%s",s);
2239                     pic16_emitcode("mov","@%s,%s",
2240                              aop->aopu.aop_ptr->name,buffer);
2241                 } else
2242                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2243         
2244         break;
2245         
2246     case AOP_STK:
2247         if (strcmp(s,"a") == 0)
2248             pic16_emitcode("push","acc");
2249         else
2250             pic16_emitcode("push","%s",s);
2251         
2252         break;
2253         
2254     case AOP_CRY:
2255         /* if bit variable */
2256         if (!aop->aopu.aop_dir) {
2257             pic16_emitcode("clr","a");
2258             pic16_emitcode("rlc","a");
2259         } else {
2260             if (s == zero) 
2261                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2262             else
2263                 if (s == one)
2264                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2265                 else
2266                     if (!strcmp(s,"c"))
2267                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2268                     else {
2269                         lbl = newiTempLabel(NULL);
2270                         
2271                         if (strcmp(s,"a")) {
2272                             MOVA(s);
2273                         }
2274                         pic16_emitcode("clr","c");
2275                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2276                         pic16_emitcode("cpl","c");
2277                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2278                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2279                     }
2280         }
2281         break;
2282         
2283     case AOP_STR:
2284         aop->coff = offset;
2285         if (strcmp(aop->aopu.aop_str[offset],s))
2286             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2287         break;
2288         
2289     case AOP_ACC:
2290         aop->coff = offset;
2291         if (!offset && (strcmp(s,"acc") == 0))
2292             break;
2293         
2294         if (strcmp(aop->aopu.aop_str[offset],s))
2295             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2296         break;
2297
2298     default :
2299         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2300 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2301 //             "pic16_aopPut got unsupported aop->type");
2302 //      exit(0);    
2303     }    
2304
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2309 /*-----------------------------------------------------------------*/
2310 void pic16_mov2w (asmop *aop, int offset)
2311 {
2312   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2313
2314   if(is_LitAOp(aop))
2315     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2316   else
2317     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2318 }
2319
2320 static void mov2f(asmop *dst, asmop *src, int offset)
2321 {
2322   if(is_LitAOp(src)) {
2323     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2324     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2325   } else {
2326     if(pic16_sameRegsOfs(src, dst, offset))return;
2327     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2328                       pic16_popGet(dst, offset)));
2329   }
2330 }
2331
2332 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2333 {
2334   if(is_LitAOp(src)) {
2335     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2336     pic16_emitpcode(POC_MOVWF, dst);
2337   } else {
2338     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2339   }
2340 }
2341
2342 void pic16_testStackOverflow(void)
2343 {
2344 #define GSTACK_TEST_NAME        "__gstack_test"
2345
2346   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2347   
2348   {
2349     symbol *sym;
2350
2351       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2352       strcpy(sym->rname, GSTACK_TEST_NAME);
2353       checkAddSym(&externs, sym);
2354   }
2355
2356 }
2357
2358 /* push pcop into stack */
2359 void pic16_pushpCodeOp(pCodeOp *pcop)
2360 {
2361 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2362   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2363   if(pic16_options.gstack)
2364     pic16_testStackOverflow();
2365     
2366 }
2367
2368 /* pop pcop from stack */
2369 void pic16_poppCodeOp(pCodeOp *pcop)
2370 {
2371   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2372   if(pic16_options.gstack)
2373     pic16_testStackOverflow();
2374 }
2375
2376
2377 /*-----------------------------------------------------------------*/
2378 /* pushw - pushes wreg to stack                                    */
2379 /*-----------------------------------------------------------------*/
2380 void pushw(void)
2381 {
2382   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2383   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2384   if(pic16_options.gstack)
2385     pic16_testStackOverflow();
2386 }
2387
2388                 
2389 /*-----------------------------------------------------------------*/
2390 /* pushaop - pushes aop to stack                                   */
2391 /*-----------------------------------------------------------------*/
2392 void pushaop(asmop *aop, int offset)
2393 {
2394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2395
2396   if(is_LitAOp(aop)) {
2397     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2398     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2399   } else {
2400     pic16_emitpcode(POC_MOVFF,
2401       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2402   }
2403
2404   if(pic16_options.gstack)
2405     pic16_testStackOverflow();
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* popaop - pops aop from stack                                    */
2410 /*-----------------------------------------------------------------*/
2411 void popaop(asmop *aop, int offset)
2412 {
2413   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2414   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2415   if(pic16_options.gstack)
2416     pic16_testStackOverflow();
2417 }
2418
2419 void popaopidx(asmop *aop, int offset, int index)
2420 {
2421   int ofs=1;
2422
2423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2424
2425     if(STACK_MODEL_LARGE)ofs++;
2426
2427     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2428     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2429     if(pic16_options.gstack)
2430       pic16_testStackOverflow();
2431 }
2432
2433 #if !(USE_GENERIC_SIGNED_SHIFT)
2434 /*-----------------------------------------------------------------*/
2435 /* reAdjustPreg - points a register back to where it should        */
2436 /*-----------------------------------------------------------------*/
2437 static void reAdjustPreg (asmop *aop)
2438 {
2439     int size ;
2440
2441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2442     aop->coff = 0;
2443     if ((size = aop->size) <= 1)
2444         return ;
2445     size-- ;
2446     switch (aop->type) {
2447         case AOP_R0 :
2448         case AOP_R1 :
2449             while (size--)
2450                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2451             break;          
2452         case AOP_DPTR :
2453         case AOP_DPTR2:
2454             if (aop->type == AOP_DPTR2)
2455             {
2456                 genSetDPTR(1);
2457             } 
2458             while (size--)
2459             {
2460                 pic16_emitcode("lcall","__decdptr");
2461             }
2462                 
2463             if (aop->type == AOP_DPTR2)
2464             {
2465                 genSetDPTR(0);
2466             }                
2467             break;  
2468
2469     }   
2470
2471 }
2472 #endif
2473
2474 #if 0
2475 /*-----------------------------------------------------------------*/
2476 /* opIsGptr: returns non-zero if the passed operand is             */   
2477 /* a generic pointer type.                                         */
2478 /*-----------------------------------------------------------------*/ 
2479 static int opIsGptr(operand *op)
2480 {
2481     sym_link *type = operandType(op);
2482     
2483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2484     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2485     {
2486         return 1;
2487     }
2488     return 0;        
2489 }
2490 #endif
2491
2492 /*-----------------------------------------------------------------*/
2493 /* pic16_getDataSize - get the operand data size                         */
2494 /*-----------------------------------------------------------------*/
2495 int pic16_getDataSize(operand *op)
2496 {
2497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2498
2499
2500     return AOP_SIZE(op);
2501
2502     // tsd- in the pic port, the genptr size is 1, so this code here
2503     // fails. ( in the 8051 port, the size was 4).
2504 #if 0
2505     int size;
2506     size = AOP_SIZE(op);
2507     if (size == GPTRSIZE)
2508     {
2509         sym_link *type = operandType(op);
2510         if (IS_GENPTR(type))
2511         {
2512             /* generic pointer; arithmetic operations
2513              * should ignore the high byte (pointer type).
2514              */
2515             size--;
2516     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2517         }
2518     }
2519     return size;
2520 #endif
2521 }
2522
2523 /*-----------------------------------------------------------------*/
2524 /* pic16_outAcc - output Acc                                             */
2525 /*-----------------------------------------------------------------*/
2526 void pic16_outAcc(operand *result)
2527 {
2528   int size,offset;
2529   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2530   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2531
2532
2533   size = pic16_getDataSize(result);
2534   if(size){
2535     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2536     size--;
2537     offset = 1;
2538     /* unsigned or positive */
2539     while(size--)
2540       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2541   }
2542
2543 }
2544
2545 /*-----------------------------------------------------------------*/
2546 /* pic16_outBitC - output a bit C                                  */
2547 /*                 Move to result the value of Carry flag -- VR    */
2548 /*-----------------------------------------------------------------*/
2549 void pic16_outBitC(operand *result)
2550 {
2551   int i;
2552
2553     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2554
2555     /* if the result is bit */
2556     if (AOP_TYPE(result) == AOP_CRY) {
2557         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2558         pic16_aopPut(AOP(result),"c",0);
2559     } else {
2560
2561         i = AOP_SIZE(result);
2562         while(i--) {
2563                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2564         }
2565         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2566     }
2567 }
2568
2569 /*-----------------------------------------------------------------*/
2570 /* pic16_outBitOp - output a bit from Op                           */
2571 /*                 Move to result the value of set/clr op -- VR    */
2572 /*-----------------------------------------------------------------*/
2573 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2574 {
2575   int i;
2576
2577     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2578
2579     /* if the result is bit */
2580     if (AOP_TYPE(result) == AOP_CRY) {
2581         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2582         pic16_aopPut(AOP(result),"c",0);
2583     } else {
2584
2585         i = AOP_SIZE(result);
2586         while(i--) {
2587                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2588         }
2589         pic16_emitpcode(POC_RRCF, pcop);          
2590         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2591     }
2592 }
2593
2594 /*-----------------------------------------------------------------*/
2595 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2596 /*-----------------------------------------------------------------*/
2597 void pic16_toBoolean(operand *oper)
2598 {
2599     int size = AOP_SIZE(oper) - 1;
2600     int offset = 1;
2601
2602     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2603
2604     if ( AOP_TYPE(oper) != AOP_ACC) {
2605       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2606     }
2607     while (size--) {
2608       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2609     }
2610 }
2611
2612
2613 #if !defined(GEN_Not)
2614 /*-----------------------------------------------------------------*/
2615 /* genNot - generate code for ! operation                          */
2616 /*-----------------------------------------------------------------*/
2617 static void pic16_genNot (iCode *ic)
2618 {
2619   symbol *tlbl;
2620   int size;
2621
2622   FENTRY;
2623   /* assign asmOps to operand & result */
2624   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2625   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2626
2627   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2628   /* if in bit space then a special case */
2629   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2630     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2631       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2632       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2633     } else {
2634       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2635       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2636       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2637     }
2638     goto release;
2639   }
2640
2641   size = AOP_SIZE(IC_LEFT(ic));
2642   if(size == 1) {
2643     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2644     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2645     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2646     goto release;
2647   }
2648   pic16_toBoolean(IC_LEFT(ic));
2649
2650   tlbl = newiTempLabel(NULL);
2651   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2652   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2653   pic16_outBitC(IC_RESULT(ic));
2654
2655  release:    
2656   /* release the aops */
2657   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2658   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2659 }
2660 #endif
2661
2662
2663 #if !defined(GEN_Cpl)
2664 /*-----------------------------------------------------------------*/
2665 /* genCpl - generate code for complement                           */
2666 /*-----------------------------------------------------------------*/
2667 static void pic16_genCpl (iCode *ic)
2668 {
2669   int offset = 0;
2670   int size ;
2671
2672     FENTRY;
2673     /* assign asmOps to operand & result */
2674     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2675     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2676
2677     /* if both are in bit space then 
2678     a special case */
2679     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2680         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2681
2682         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2683         pic16_emitcode("cpl","c"); 
2684         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2685         goto release; 
2686     } 
2687
2688     size = AOP_SIZE(IC_RESULT(ic));
2689     while (size--) {
2690 /*
2691         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2692         MOVA(l);       
2693         pic16_emitcode("cpl","a");
2694         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2695 */
2696         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2697               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2698         } else {
2699                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2700                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2701         }
2702         offset++;
2703
2704     }
2705
2706
2707 release:
2708     /* release the aops */
2709     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2710     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2711 }
2712 #endif
2713
2714 /*-----------------------------------------------------------------*/
2715 /* genUminusFloat - unary minus for floating points                */
2716 /*-----------------------------------------------------------------*/
2717 static void genUminusFloat(operand *op,operand *result)
2718 {
2719   int size ,offset =0 ;
2720   
2721     FENTRY;
2722     /* for this we just need to flip the 
2723     first it then copy the rest in place */
2724     size = AOP_SIZE(op);
2725
2726     while(size--) {
2727       mov2f(AOP(result), AOP(op), offset);
2728       offset++;
2729     }
2730     
2731     /* toggle the MSB's highest bit */
2732     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2733 }
2734
2735 /*-----------------------------------------------------------------*/
2736 /* genUminus - unary minus code generation                         */
2737 /*-----------------------------------------------------------------*/
2738 static void genUminus (iCode *ic)
2739 {
2740   int size, i;
2741   sym_link *optype, *rtype;
2742   symbol *label;
2743   int needLabel=0;
2744
2745     FENTRY;     
2746     
2747     /* assign asmops */
2748     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2749     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2750
2751     /* if both in bit space then special case */
2752     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2753       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2754         
2755         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2756         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2757         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2758         goto release; 
2759     } 
2760
2761     optype = operandType(IC_LEFT(ic));
2762     rtype = operandType(IC_RESULT(ic));
2763
2764     /* if float then do float stuff */
2765     if (IS_FLOAT(optype)) {
2766       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2767       goto release;
2768     }
2769
2770     /* otherwise subtract from zero by taking the 2's complement */
2771     size = AOP_SIZE(IC_LEFT(ic));
2772     label = newiTempLabel ( NULL );
2773     
2774     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2775       for (i=size-1; i > 0; i--) {
2776         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2777       } // for
2778       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2779       for (i=1; i < size; i++) {
2780         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2781         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2782       } // for
2783     } else {
2784       for (i=size-1; i >= 0; i--) {
2785         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2786         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2787       } // for
2788       if (size > 1) {
2789         for (i=0; i < size-2; i++) {
2790           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2791           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2792         } // for
2793         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2794       } // if
2795       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2796     }
2797     if (needLabel)
2798       pic16_emitpLabel (label->key);
2799
2800 release:
2801     /* release the aops */
2802     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2803     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2804 }
2805
2806 #if 0
2807 /*-----------------------------------------------------------------*/
2808 /* saveRegisters - will look for a call and save the registers     */
2809 /*-----------------------------------------------------------------*/
2810 static void saveRegisters(iCode *lic) 
2811 {
2812     int i;
2813     iCode *ic;
2814     bitVect *rsave;
2815     sym_link *dtype;
2816
2817     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2818     /* look for call */
2819     for (ic = lic ; ic ; ic = ic->next) 
2820         if (ic->op == CALL || ic->op == PCALL)
2821             break;
2822
2823     if (!ic) {
2824         fprintf(stderr,"found parameter push with no function call\n");
2825         return ;
2826     }
2827
2828     /* if the registers have been saved already then
2829     do nothing */
2830     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2831         return ;
2832
2833     /* find the registers in use at this time 
2834     and push them away to safety */
2835     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2836                           ic->rUsed);
2837
2838     ic->regsSaved = 1;
2839     if (options.useXstack) {
2840         if (bitVectBitValue(rsave,R0_IDX))
2841             pic16_emitcode("mov","b,r0");
2842         pic16_emitcode("mov","r0,%s",spname);
2843         for (i = 0 ; i < pic16_nRegs ; i++) {
2844             if (bitVectBitValue(rsave,i)) {
2845                 if (i == R0_IDX)
2846                     pic16_emitcode("mov","a,b");
2847                 else
2848                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2849                 pic16_emitcode("movx","@r0,a");
2850                 pic16_emitcode("inc","r0");
2851             }
2852         }
2853         pic16_emitcode("mov","%s,r0",spname);
2854         if (bitVectBitValue(rsave,R0_IDX))
2855             pic16_emitcode("mov","r0,b");           
2856     }// else
2857     //for (i = 0 ; i < pic16_nRegs ; i++) {
2858     //    if (bitVectBitValue(rsave,i))
2859     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2860     //}
2861
2862     dtype = operandType(IC_LEFT(ic));
2863     if (currFunc && dtype && 
2864         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2865         IFFUNC_ISISR(currFunc->type) &&
2866         !ic->bankSaved) 
2867
2868         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2869
2870 }
2871 /*-----------------------------------------------------------------*/
2872 /* unsaveRegisters - pop the pushed registers                      */
2873 /*-----------------------------------------------------------------*/
2874 static void unsaveRegisters (iCode *ic)
2875 {
2876     int i;
2877     bitVect *rsave;
2878
2879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2880     /* find the registers in use at this time 
2881     and push them away to safety */
2882     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2883                           ic->rUsed);
2884     
2885     if (options.useXstack) {
2886         pic16_emitcode("mov","r0,%s",spname);   
2887         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2888             if (bitVectBitValue(rsave,i)) {
2889                 pic16_emitcode("dec","r0");
2890                 pic16_emitcode("movx","a,@r0");
2891                 if (i == R0_IDX)
2892                     pic16_emitcode("mov","b,a");
2893                 else
2894                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2895             }       
2896
2897         }
2898         pic16_emitcode("mov","%s,r0",spname);
2899         if (bitVectBitValue(rsave,R0_IDX))
2900             pic16_emitcode("mov","r0,b");
2901     } //else
2902     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2903     //    if (bitVectBitValue(rsave,i))
2904     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2905     //}
2906
2907 }  
2908 #endif
2909
2910 #if 0  // patch 14
2911 /*-----------------------------------------------------------------*/
2912 /* pushSide -                                                      */
2913 /*-----------------------------------------------------------------*/
2914 static void pushSide(operand * oper, int size)
2915 {
2916         int offset = 0;
2917     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2918         while (size--) {
2919                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2920                 if (AOP_TYPE(oper) != AOP_REG &&
2921                     AOP_TYPE(oper) != AOP_DIR &&
2922                     strcmp(l,"a") ) {
2923                         pic16_emitcode("mov","a,%s",l);
2924                         pic16_emitcode("push","acc");
2925                 } else
2926                         pic16_emitcode("push","%s",l);
2927         }
2928 }
2929 #endif // patch 14
2930
2931 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2932 {
2933   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2934     pic16_emitpcode(POC_MOVFW, src);
2935     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2936   } else {
2937     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2938         src, pic16_popGet(AOP(op), offset)));
2939   }
2940 }
2941
2942
2943 /*-----------------------------------------------------------------*/
2944 /* assignResultValue - assign results to oper, rescall==1 is       */
2945 /*                     called from genCall() or genPcall()         */
2946 /*-----------------------------------------------------------------*/
2947 static void assignResultValue(operand * oper, int rescall)
2948 {
2949   int size = AOP_SIZE(oper);
2950   int offset=0;
2951   
2952     FENTRY2;
2953 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2954     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2955
2956     if(rescall) {
2957       /* assign result from a call/pcall function() */
2958                 
2959       /* function results are stored in a special order,
2960        * see top of file with Function return policy, or manual */
2961
2962       if(size <= 4) {
2963         /* 8-bits, result in WREG */
2964         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2965                         
2966         if(size>1) {
2967           /* 16-bits, result in PRODL:WREG */
2968           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2969         }
2970                         
2971         if(size>2) {
2972           /* 24-bits, result in PRODH:PRODL:WREG */
2973           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2974         }
2975                         
2976         if(size>3) {
2977           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2978           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2979         }
2980       
2981       } else {
2982         /* >32-bits, result on stack, and FSR0 points to beginning.
2983          * Fix stack when done */
2984         /* FIXME FIXME */
2985 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2986         while (size--) {
2987 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2988 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2989                 
2990           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2991           GpsuedoStkPtr++;
2992         }
2993                         
2994         /* fix stack */
2995         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2996         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2997         if(STACK_MODEL_LARGE) {
2998           emitSKPNC;
2999           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3000         }
3001       }                 
3002     } else {
3003       int areg = 0;             /* matching argument register */
3004       
3005 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3006       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3007
3008
3009       /* its called from genReceive (probably) -- VR */
3010       /* I hope this code will not be called from somewhere else in the future! 
3011        * We manually set the pseudo stack pointer in genReceive. - dw
3012        */
3013       if(!GpsuedoStkPtr && _G.useWreg) {
3014 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3015
3016         /* The last byte in the assignment is in W */
3017         if(areg <= GpsuedoStkPtr) {
3018           size--;
3019           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3020           offset++;
3021 //          debugf("receive from WREG\n", 0);
3022         }
3023         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3024       }
3025 //      GpsuedoStkPtr++;
3026       _G.stack_lat = AOP_SIZE(oper)-1;
3027
3028       while (size) {
3029         size--;
3030         GpsuedoStkPtr++;
3031         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3032 //        debugf("receive from STACK\n", 0);
3033         offset++;
3034       }
3035     }
3036 }
3037
3038
3039 /*-----------------------------------------------------------------*/
3040 /* genIpush - generate code for pushing this gets a little complex */
3041 /*-----------------------------------------------------------------*/
3042 static void genIpush (iCode *ic)
3043 {
3044 //  int size, offset=0;
3045
3046   FENTRY;
3047   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3048
3049   if(ic->parmPush) {
3050     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3051
3052     /* send to stack as normal */
3053     addSet(&_G.sendSet,ic);
3054 //    addSetHead(&_G.sendSet,ic);
3055     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3056   }
3057
3058         
3059 #if 0
3060     int size, offset = 0 ;
3061     char *l;
3062
3063
3064     /* if this is not a parm push : ie. it is spill push 
3065     and spill push is always done on the local stack */
3066     if (!ic->parmPush) {
3067
3068         /* and the item is spilt then do nothing */
3069         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3070             return ;
3071
3072         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3073         size = AOP_SIZE(IC_LEFT(ic));
3074         /* push it on the stack */
3075         while(size--) {
3076             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3077             if (*l == '#') {
3078                 MOVA(l);
3079                 l = "acc";
3080             }
3081             pic16_emitcode("push","%s",l);
3082         }
3083         return ;        
3084     }
3085
3086     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3087 #endif
3088 }
3089
3090 /*-----------------------------------------------------------------*/
3091 /* genIpop - recover the registers: can happen only for spilling   */
3092 /*-----------------------------------------------------------------*/
3093 static void genIpop (iCode *ic)
3094 {
3095   FENTRY;
3096   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3097 #if 0
3098     int size,offset ;
3099
3100
3101     /* if the temp was not pushed then */
3102     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3103         return ;
3104
3105     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3106     size = AOP_SIZE(IC_LEFT(ic));
3107     offset = (size-1);
3108     while (size--) 
3109         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3110                                    FALSE,TRUE));
3111
3112     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3113 #endif
3114 }
3115
3116 #if 0
3117 /*-----------------------------------------------------------------*/
3118 /* unsaverbank - restores the resgister bank from stack            */
3119 /*-----------------------------------------------------------------*/
3120 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3121 {
3122   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3123 #if 0
3124     int i;
3125     asmop *aop ;
3126     regs *r = NULL;
3127
3128     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3129     if (popPsw) {
3130         if (options.useXstack) {
3131             aop = newAsmop(0);
3132             r = getFreePtr(ic,&aop,FALSE);
3133             
3134             
3135             pic16_emitcode("mov","%s,_spx",r->name);
3136             pic16_emitcode("movx","a,@%s",r->name);
3137             pic16_emitcode("mov","psw,a");
3138             pic16_emitcode("dec","%s",r->name);
3139             
3140         }else
3141             pic16_emitcode ("pop","psw");
3142     }
3143
3144     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3145         if (options.useXstack) {       
3146             pic16_emitcode("movx","a,@%s",r->name);
3147             //pic16_emitcode("mov","(%s+%d),a",
3148             //       regspic16[i].base,8*bank+regspic16[i].offset);
3149             pic16_emitcode("dec","%s",r->name);
3150
3151         } else 
3152           pic16_emitcode("pop",""); //"(%s+%d)",
3153         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3154     }
3155
3156     if (options.useXstack) {
3157
3158         pic16_emitcode("mov","_spx,%s",r->name);
3159         pic16_freeAsmop(NULL,aop,ic,TRUE);
3160
3161     }
3162 #endif 
3163 }
3164
3165 /*-----------------------------------------------------------------*/
3166 /* saverbank - saves an entire register bank on the stack          */
3167 /*-----------------------------------------------------------------*/
3168 static void saverbank (int bank, iCode *ic, bool pushPsw)
3169 {
3170   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3171 #if 0
3172     int i;
3173     asmop *aop ;
3174     regs *r = NULL;
3175
3176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3177     if (options.useXstack) {
3178
3179         aop = newAsmop(0);
3180         r = getFreePtr(ic,&aop,FALSE);  
3181         pic16_emitcode("mov","%s,_spx",r->name);
3182
3183     }
3184
3185     for (i = 0 ; i < pic16_nRegs ;i++) {
3186         if (options.useXstack) {
3187             pic16_emitcode("inc","%s",r->name);
3188             //pic16_emitcode("mov","a,(%s+%d)",
3189             //         regspic16[i].base,8*bank+regspic16[i].offset);
3190             pic16_emitcode("movx","@%s,a",r->name);           
3191         } else 
3192           pic16_emitcode("push","");// "(%s+%d)",
3193                      //regspic16[i].base,8*bank+regspic16[i].offset);
3194     }
3195     
3196     if (pushPsw) {
3197         if (options.useXstack) {
3198             pic16_emitcode("mov","a,psw");
3199             pic16_emitcode("movx","@%s,a",r->name);     
3200             pic16_emitcode("inc","%s",r->name);
3201             pic16_emitcode("mov","_spx,%s",r->name);       
3202             pic16_freeAsmop (NULL,aop,ic,TRUE);
3203             
3204         } else
3205             pic16_emitcode("push","psw");
3206         
3207         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3208     }
3209     ic->bankSaved = 1;
3210 #endif
3211 }
3212 #endif  /* 0 */
3213
3214
3215 static int wparamCmp(void *p1, void *p2)
3216 {
3217   return (!strcmp((char *)p1, (char *)p2));
3218 }
3219
3220 int inWparamList(char *s)
3221 {
3222   return isinSetWith(wparamList, s, wparamCmp);
3223
3224
3225
3226 /*-----------------------------------------------------------------*/
3227 /* genCall - generates a call statement                            */
3228 /*-----------------------------------------------------------------*/
3229 static void genCall (iCode *ic)
3230 {
3231   sym_link *ftype;   
3232   int stackParms=0;
3233   int use_wreg=0;
3234   int inwparam=0;
3235   char *fname;
3236   
3237     FENTRY;
3238
3239     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3240     /* if caller saves & we have not saved then */
3241 //    if (!ic->regsSaved)
3242 //      saveRegisters(ic);
3243
3244         /* initialise stackParms for IPUSH pushes */
3245 //      stackParms = psuedoStkPtr;
3246 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3247     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3248     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3249
3250 #if 0
3251     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3252 #endif
3253
3254     /* if send set is not empty the assign */
3255     if (_G.sendSet) {
3256       iCode *sic;
3257       int psuedoStkPtr=-1; 
3258       int firstTimeThruLoop = 1;
3259
3260
3261         /* reverse sendSet if function is not reentrant */
3262         if(!IFFUNC_ISREENT(ftype))
3263           _G.sendSet = reverseSet(_G.sendSet);
3264
3265         /* First figure how many parameters are getting passed */
3266         stackParms = 0;
3267         use_wreg = 0;
3268         
3269         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3270           int size;
3271 //          int offset = 0;
3272
3273             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3274             size = AOP_SIZE(IC_LEFT(sic));
3275
3276             stackParms += size;
3277
3278             /* pass the last byte through WREG */
3279             if(inwparam) {
3280
3281               while (size--) {
3282                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3283                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3284                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3285
3286                 if(!firstTimeThruLoop) {
3287                   /* If this is not the first time we've been through the loop
3288                    * then we need to save the parameter in a temporary
3289                    * register. The last byte of the last parameter is
3290                    * passed in W. */
3291
3292                   pushw();
3293 //                  --psuedoStkPtr;             // sanity check
3294                   use_wreg = 1;
3295                 }
3296                 
3297                 firstTimeThruLoop=0;
3298
3299                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3300
3301 //                offset++;
3302               }
3303             } else {
3304               /* all arguments are passed via stack */
3305               use_wreg = 0;
3306
3307               while (size--) {
3308                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3309                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3310                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3311
3312 //                pushaop(AOP(IC_LEFT(sic)), size);
3313                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3314                 pushw();
3315               }
3316             }
3317
3318             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3319           }
3320
3321           if(inwparam) {
3322             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3323               pushw();  /* save last parameter to stack if functions has varargs */
3324               use_wreg = 0;
3325             } else
3326               use_wreg = 1;
3327           } else use_wreg = 0;
3328
3329           _G.stackRegSet = _G.sendSet;
3330           _G.sendSet = NULL;
3331     }
3332
3333     /* make the call */
3334     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3335
3336     GpsuedoStkPtr=0;
3337     
3338     /* if we need to assign a result value */
3339     if ((IS_ITEMP(IC_RESULT(ic))
3340           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3341               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3342         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3343
3344       _G.accInUse++;
3345       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3346       _G.accInUse--;
3347
3348       assignResultValue(IC_RESULT(ic), 1);
3349
3350       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3351                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3352                 
3353       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3354     }
3355
3356     if(!stackParms && ic->parmBytes) {
3357       stackParms = ic->parmBytes;
3358     }
3359       
3360     stackParms -= use_wreg;
3361     
3362     if(stackParms>0) {
3363       if(stackParms == 1) {
3364         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3365       } else {
3366         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3367         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3368       }
3369       if(STACK_MODEL_LARGE) {
3370         emitSKPNC;
3371         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3372       }
3373     }
3374
3375 #if 0
3376     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3377 #endif
3378
3379     /* adjust the stack for parameters if required */
3380 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3381
3382 #if 0
3383       /* if register bank was saved then pop them */
3384       if (ic->bankSaved)
3385         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3386
3387       /* if we hade saved some registers then unsave them */
3388       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3389         unsaveRegisters (ic);
3390 #endif
3391 }
3392
3393
3394
3395 /*-----------------------------------------------------------------*/
3396 /* genPcall - generates a call by pointer statement                */
3397 /*            new version, created from genCall - HJD              */
3398 /*-----------------------------------------------------------------*/
3399 static void genPcall (iCode *ic)
3400 {
3401   sym_link *ftype, *fntype;
3402   int stackParms=0;
3403   symbol *retlbl = newiTempLabel(NULL);
3404   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3405   
3406     FENTRY;
3407
3408     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3409     fntype = operandType( IC_LEFT(ic) )->next;
3410
3411     /* if send set is not empty the assign */
3412     if (_G.sendSet) {
3413       iCode *sic;
3414       int psuedoStkPtr=-1; 
3415
3416       /* reverse sendSet if function is not reentrant */
3417       if(!IFFUNC_ISREENT(fntype))
3418         _G.sendSet = reverseSet(_G.sendSet);
3419
3420       stackParms = 0;
3421       
3422       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3423         int size;
3424
3425           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3426           size = AOP_SIZE(IC_LEFT(sic));
3427           stackParms += size;
3428
3429           /* all parameters are passed via stack, since WREG is clobbered
3430            * by the calling sequence */
3431           while (size--) {
3432             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3433             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3434             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3435
3436             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3437             pushw();
3438           }
3439
3440           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3441       }
3442
3443       _G.stackRegSet = _G.sendSet;
3444       _G.sendSet = NULL;
3445     }
3446
3447     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3448
3449     // push return address
3450     // push $ on return stack, then replace with retlbl
3451
3452     /* Thanks to Thorsten Klose for pointing out that the following
3453      * snippet should be interrupt safe */
3454     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3455     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3456
3457     pic16_emitpcodeNULLop(POC_PUSH);
3458
3459     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3460     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3461     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3462     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3463     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3465
3466
3467     /* restore interrupt control register */
3468     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3469     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3470
3471     /* make the call by writing the pointer into pc */
3472     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3473     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3474
3475     // note: MOVFF to PCL not allowed
3476     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3477     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3478
3479
3480     /* return address is here: (X) */
3481     pic16_emitpLabelFORCE(retlbl->key);
3482
3483     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3484
3485     GpsuedoStkPtr=0;
3486     /* if we need assign a result value */
3487     if ((IS_ITEMP(IC_RESULT(ic))
3488           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3489               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3490         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3491
3492       _G.accInUse++;
3493       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3494       _G.accInUse--;
3495
3496       assignResultValue(IC_RESULT(ic), 1);
3497
3498       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3500                 
3501       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3502     }
3503
3504 //    stackParms -= use_wreg;
3505     
3506     if(stackParms>0) {
3507       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3508       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3509       if(STACK_MODEL_LARGE) {
3510         emitSKPNC;
3511         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3512       }
3513     }
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* resultRemat - result  is rematerializable                       */
3518 /*-----------------------------------------------------------------*/
3519 static int resultRemat (iCode *ic)
3520 {
3521   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3522   if (SKIP_IC(ic) || ic->op == IFX)
3523     return 0;
3524
3525   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3526     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3527     if (sym->remat && !POINTER_SET(ic)) 
3528       return 1;
3529   }
3530
3531   return 0;
3532 }
3533
3534 #if defined(__BORLANDC__) || defined(_MSC_VER)
3535 #define STRCASECMP stricmp
3536 #else
3537 #define STRCASECMP strcasecmp
3538 #endif
3539
3540 #if 0
3541 /*-----------------------------------------------------------------*/
3542 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3543 /*-----------------------------------------------------------------*/
3544 static bool inExcludeList(char *s)
3545 {
3546   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3547     int i =0;
3548     
3549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3550     if (options.excludeRegs[i] &&
3551     STRCASECMP(options.excludeRegs[i],"none") == 0)
3552         return FALSE ;
3553
3554     for ( i = 0 ; options.excludeRegs[i]; i++) {
3555         if (options.excludeRegs[i] &&
3556         STRCASECMP(s,options.excludeRegs[i]) == 0)
3557             return TRUE;
3558     }
3559     return FALSE ;
3560 }
3561 #endif
3562
3563 /*-----------------------------------------------------------------*/
3564 /* genFunction - generated code for function entry                 */
3565 /*-----------------------------------------------------------------*/
3566 static void genFunction (iCode *ic)
3567 {
3568   symbol *sym;
3569   sym_link *ftype;
3570   
3571     FENTRY;
3572     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3573
3574     pic16_labelOffset += (max_key+4);
3575     max_key=0;
3576     GpsuedoStkPtr=0;
3577     _G.nRegsSaved = 0;
3578         
3579     ftype = operandType(IC_LEFT(ic));
3580     sym = OP_SYMBOL(IC_LEFT(ic));
3581
3582     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3583       /* create an absolute section at the interrupt vector:
3584        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3585       symbol *asym;
3586       char asymname[128];
3587       pBlock *apb;
3588
3589 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3590
3591 #if 0
3592         {
3593           int i, found=-1;
3594
3595             sym = OP_SYMBOL( IC_LEFT(ic));
3596             for(i=0;i<=2;i++) {
3597               if(interrupts[i]->name
3598                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3599                   found = i;
3600                   break;
3601               }
3602             }
3603                         
3604             if(found == -1) {
3605               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3606                             __FILE__, __LINE__, sym->name);
3607 //              assert( 0 );
3608             }
3609             _G.interruptvector = found;
3610         }
3611 #endif
3612
3613         if(FUNC_INTNO(sym->type) == 256)
3614           sprintf(asymname, "ivec_%s", sym->name);
3615         else
3616           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3617         asym = newSymbol(asymname, 0);
3618
3619         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3620         pic16_addpBlock( apb );
3621
3622         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3623         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3624         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3625                 
3626         /* mark the end of this tiny function */
3627         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3628
3629         {
3630           absSym *abSym;
3631
3632             abSym = Safe_calloc(1, sizeof(absSym));
3633             strcpy(abSym->name, asymname);
3634
3635             switch( FUNC_INTNO(sym->type) ) {
3636               case 0: abSym->address = 0x000000; break;
3637               case 1: abSym->address = 0x000008; break;
3638               case 2: abSym->address = 0x000018; break;
3639               
3640               default:
3641                 abSym->address = -1; break;
3642             }
3643
3644             /* relocate interrupt vectors if needed */
3645             if(abSym->address != -1)
3646               abSym->address += pic16_options.ivt_loc;
3647
3648             addSet(&absSymSet, abSym);
3649         }
3650     }
3651
3652     /* create the function header */
3653     pic16_emitcode(";","-----------------------------------------");
3654     pic16_emitcode(";"," function %s",sym->name);
3655     pic16_emitcode(";","-----------------------------------------");
3656
3657     pic16_emitcode("","%s:",sym->rname);
3658     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3659
3660
3661     {
3662       absSym *ab;
3663
3664         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3665           if(!strcmp(ab->name, sym->rname)) {
3666             pic16_pBlockConvert2Absolute(pb);
3667             break;
3668           }
3669         }
3670     }
3671
3672
3673     if(IFFUNC_ISNAKED(ftype)) {
3674       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3675       return;
3676     }
3677         
3678     /* if critical function then turn interrupts off */
3679     if (IFFUNC_ISCRITICAL(ftype)) {
3680       //pic16_emitcode("clr","ea");
3681     }
3682
3683     _G.fregsUsed = sym->regsUsed;
3684
3685     /* if this is an interrupt service routine then
3686      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3687     if (IFFUNC_ISISR(sym->type)) {
3688         _G.usefastretfie = 1;   /* use shadow registers by default */
3689         
3690         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3691         if(!FUNC_ISSHADOWREGS(sym->type)) {
3692           /* do not save WREG,STATUS,BSR for high priority interrupts
3693            * because they are stored in the hardware shadow registers already */
3694           _G.usefastretfie = 0;
3695           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3696           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3697           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3698         }
3699
3700         /* these should really be optimized somehow, because not all
3701          * interrupt handlers modify them */
3702         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3703         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3704         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3705         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3706         
3707 //        pic16_pBlockConvert2ISR(pb);
3708                 
3709     }
3710
3711     /* emit code to setup stack frame if user enabled,
3712      * and function is not main() */
3713     
3714     //fprintf(stderr, "function name: %s\n", sym->name);
3715     if(strcmp(sym->name, "main")) {
3716       if(0 || !options.ommitFramePtr || sym->regsUsed) {
3717         /* setup the stack frame */
3718         if(STACK_MODEL_LARGE)
3719           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3720         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3721
3722         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3723         if(STACK_MODEL_LARGE)
3724           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3725       }
3726     }
3727
3728     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3729           && sym->stack) {
3730
3731       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3732
3733       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3734       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3735       emitSKPC;
3736       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3737     }
3738           
3739     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3740       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3741         _G.useWreg = 0;
3742       else
3743         _G.useWreg = 1;
3744     } else
3745       _G.useWreg = 0;
3746
3747     /* if callee-save to be used for this function
3748      * then save the registers being used in this function */
3749 //    if (IFFUNC_CALLEESAVES(sym->type))
3750     {
3751       int i;
3752
3753         /* if any registers used */
3754         if (sym->regsUsed) {
3755           /* save the registers used */
3756           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3757           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3758           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3759             if (bitVectBitValue(sym->regsUsed,i)) {
3760               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3761               _G.nRegsSaved++;
3762
3763               if(!pic16_regWithIdx(i)->wasUsed) {
3764                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3765                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3766                 pic16_regWithIdx(i)->wasUsed = 1;
3767               }
3768             }
3769           }
3770           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3771         }
3772     }
3773         
3774     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3775 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3776 }
3777
3778 /*-----------------------------------------------------------------*/
3779 /* genEndFunction - generates epilogue for functions               */
3780 /*-----------------------------------------------------------------*/
3781 static void genEndFunction (iCode *ic)
3782 {
3783   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3784
3785     FENTRY;
3786
3787     if(IFFUNC_ISNAKED(sym->type)) {
3788       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3789       return;
3790     }
3791
3792     _G.stack_lat = 0;
3793
3794     /* add code for ISCRITICAL */
3795     if(IFFUNC_ISCRITICAL(sym->type)) {
3796       /* if critical function, turn on interrupts */
3797       
3798       /* TODO: add code here -- VR */
3799     }
3800     
3801 //    sym->regsUsed = _G.fregsUsed;
3802     
3803     /* now we need to restore the registers */
3804     /* if any registers used */
3805     if (sym->regsUsed) {
3806       int i;
3807
3808         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3809         /* restore registers used */
3810         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3811         for ( i = sym->regsUsed->size; i >= 0; i--) {
3812           if (bitVectBitValue(sym->regsUsed,i)) {
3813             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3814             _G.nRegsSaved--;
3815           }
3816         }
3817         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3818
3819     }
3820
3821     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3822           && sym->stack) {
3823       if (sym->stack == 1) {
3824         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3825         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3826       } else {
3827         // we have to add more than one...
3828         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3829         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3830         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3831         emitSKPNC;
3832         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3833         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3834         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3835       }
3836     }
3837
3838     if(strcmp(sym->name, "main")) {
3839       if(0 || !options.ommitFramePtr || sym->regsUsed) {
3840         /* restore stack frame */
3841         if(STACK_MODEL_LARGE)
3842           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3843         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3844       }
3845     }
3846
3847     _G.useWreg = 0;
3848
3849     if (IFFUNC_ISISR(sym->type)) {
3850       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3851       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3852       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3853       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3854
3855       if(!FUNC_ISSHADOWREGS(sym->type)) {
3856         /* do not restore interrupt vector for WREG,STATUS,BSR
3857          * for high priority interrupt, see genFunction */
3858         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3859         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3860         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3861       }
3862 //      _G.interruptvector = 0;         /* sanity check */
3863
3864
3865       /* if debug then send end of function */
3866 /*      if (options.debug && currFunc)  */
3867       if (currFunc) {
3868         debugFile->writeEndFunction (currFunc, ic, 1);
3869       }
3870         
3871       if(_G.usefastretfie)
3872         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3873       else
3874         pic16_emitpcodeNULLop(POC_RETFIE);
3875
3876       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3877       
3878       _G.usefastretfie = 0;
3879       return;
3880     }
3881
3882     if (IFFUNC_ISCRITICAL(sym->type)) {
3883       pic16_emitcode("setb","ea");
3884     }
3885
3886     /* if debug then send end of function */
3887     if (currFunc) {
3888       debugFile->writeEndFunction (currFunc, ic, 1);
3889     }
3890
3891     /* insert code to restore stack frame, if user enabled it
3892      * and function is not main() */
3893          
3894
3895     pic16_emitpcodeNULLop(POC_RETURN);
3896
3897     /* Mark the end of a function */
3898     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3899 }
3900
3901
3902 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3903 {
3904   unsigned long lit=1;
3905  
3906   // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3907   if(AOP_TYPE(op) == AOP_LIT) {
3908     if(!IS_FLOAT(operandType( op ))) {
3909       lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3910     } else {
3911       union {
3912         unsigned long lit_int;
3913         float lit_float;
3914       } info;
3915         
3916       /* take care if literal is a float */
3917       info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3918       lit = info.lit_int;
3919     }
3920   }
3921
3922   if(is_LitOp(op)) {
3923       if(lit == 0) {
3924         pic16_emitpcode(POC_CLRF, dest);
3925       } else {
3926         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3927         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3928       }
3929   } else {
3930     if(dest->type == PO_WREG && (offset == 0)) {
3931       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3932       return;
3933     }
3934     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3935   }
3936 }
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genRet - generate code for return statement                     */
3940 /*-----------------------------------------------------------------*/
3941 static void genRet (iCode *ic)
3942 {
3943   int size;
3944   operand *left;
3945
3946     FENTRY;
3947         /* if we have no return value then
3948          * just generate the "ret" */
3949         
3950         if (!IC_LEFT(ic)) 
3951                 goto jumpret;       
3952     
3953         /* we have something to return then
3954          * move the return value into place */
3955         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3956         size = AOP_SIZE(IC_LEFT(ic));
3957
3958         if(size <= 4) {
3959                 if(size>3) {
3960                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3961 //                      pic16_emitpcode(POC_MOVFF,
3962 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3963                 }
3964                 if(size>2) {
3965                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3966 //                      pic16_emitpcode(POC_MOVFF,
3967 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3968                 }
3969                 if(size>1) {
3970                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3971 //                      pic16_emitpcode(POC_MOVFF,
3972 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3973                 }
3974
3975 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3976
3977                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3978 //              pic16_emitpcode(POC_MOVFF,
3979 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3980
3981         } else {
3982                 /* >32-bits, setup stack and FSR0 */
3983                 while (size--) {
3984 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3985 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3986
3987                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3988
3989 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3990                         GpsuedoStkPtr++;
3991                 }
3992                         
3993                 /* setup FSR0 */
3994                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3996
3997                 if(STACK_MODEL_LARGE) {
3998                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3999                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4000                 } else {
4001                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4002                 }
4003         }
4004                                 
4005 #if 0
4006         /* old code, left here for reference -- VR */    
4007         while (size--) {
4008           char *l ;
4009
4010                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4011                         /* #NOCHANGE */
4012                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4013                         pic16_emitpcomment("push %s",l);
4014                         pushed++;
4015                 } else {
4016                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4017                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4018                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4019                         
4020                         if (strcmp(fReturn[offset],l)) {
4021                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4022                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4023                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4024                                 } else {
4025                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4026                                 }
4027                                 
4028                                 if(size) {
4029                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4030                                 }
4031                                 offset++;
4032                         }
4033                 }
4034         }    
4035
4036         if (pushed) {
4037                 while(pushed) {
4038                         pushed--;
4039                         if (strcmp(fReturn[pushed],"a"))
4040                                 pic16_emitcode("pop",fReturn[pushed]);
4041                         else
4042                                 pic16_emitcode("pop","acc");
4043                 }
4044         }
4045 #endif
4046
4047
4048         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4049     
4050 jumpret:
4051         /* generate a jump to the return label
4052          * if the next is not the return statement */
4053         if (!(ic->next && ic->next->op == LABEL
4054                 && IC_LABEL(ic->next) == returnLabel)) {
4055         
4056                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4057                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4058         }
4059 }
4060
4061 /*-----------------------------------------------------------------*/
4062 /* genLabel - generates a label                                    */
4063 /*-----------------------------------------------------------------*/
4064 static void genLabel (iCode *ic)
4065 {
4066   FENTRY;
4067
4068   /* special case never generate */
4069   if (IC_LABEL(ic) == entryLabel)
4070     return ;
4071
4072   pic16_emitpLabel(IC_LABEL(ic)->key);
4073 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4074 }
4075
4076 /*-----------------------------------------------------------------*/
4077 /* genGoto - generates a goto                                      */
4078 /*-----------------------------------------------------------------*/
4079 //tsd
4080 static void genGoto (iCode *ic)
4081 {
4082   FENTRY;
4083   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4084 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4085 }
4086
4087
4088 /*-----------------------------------------------------------------*/
4089 /* genMultbits :- multiplication of bits                           */
4090 /*-----------------------------------------------------------------*/
4091 static void genMultbits (operand *left, 
4092                          operand *right, 
4093                          operand *result)
4094 {
4095   FENTRY;
4096
4097   if(!pic16_sameRegs(AOP(result),AOP(right)))
4098     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4099
4100   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4101   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4102   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4103
4104 }
4105
4106
4107 /*-----------------------------------------------------------------*/
4108 /* genMultOneByte : 8 bit multiplication & division                */
4109 /*-----------------------------------------------------------------*/
4110 static void genMultOneByte (operand *left,
4111                             operand *right,
4112                             operand *result)
4113 {
4114
4115   FENTRY;
4116   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4117   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4118
4119   /* (if two literals, the value is computed before) */
4120   /* if one literal, literal on the right */
4121   if (AOP_TYPE(left) == AOP_LIT){
4122     operand *t = right;
4123     right = left;
4124     left = t;
4125   }
4126
4127         /* size is already checked in genMult == 1 */
4128 //      size = AOP_SIZE(result);
4129
4130         if (AOP_TYPE(right) == AOP_LIT){
4131                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4132                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4133                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4134                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4135         } else {
4136                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4137                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4138                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4139                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4140         }
4141         
4142         pic16_genMult8X8_8 (left, right,result);
4143 }
4144
4145 /*-----------------------------------------------------------------*/
4146 /* genMultOneWord : 16 bit multiplication                          */
4147 /*-----------------------------------------------------------------*/
4148 static void genMultOneWord (operand *left,
4149                             operand *right,
4150                             operand *result)
4151 {
4152   FENTRY;
4153   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4154   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4155
4156   /* (if two literals, the value is computed before)
4157    * if one literal, literal on the right */
4158   if (AOP_TYPE(left) == AOP_LIT){
4159     operand *t = right;
4160     right = left;
4161     left = t;
4162   }
4163
4164   /* size is checked already == 2 */
4165 //  size = AOP_SIZE(result);
4166
4167   if (AOP_TYPE(right) == AOP_LIT) {
4168     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4169       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4170       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4171       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4172   } else {
4173     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4174       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4175       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4176       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4177   }
4178         
4179   pic16_genMult16X16_16(left, right,result);
4180 }
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genMultOneLong : 32 bit multiplication                          */
4184 /*-----------------------------------------------------------------*/
4185 static void genMultOneLong (operand *left,
4186                             operand *right,
4187                             operand *result)
4188 {
4189   FENTRY;
4190   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4192
4193   /* (if two literals, the value is computed before)
4194    * if one literal, literal on the right */
4195   if (AOP_TYPE(left) == AOP_LIT){
4196     operand *t = right;
4197     right = left;
4198     left = t;
4199   }
4200
4201   /* size is checked already == 4 */
4202 //  size = AOP_SIZE(result);
4203
4204   if (AOP_TYPE(right) == AOP_LIT) {
4205     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4206         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4207         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4208         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4209   } else {
4210     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4211         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4212         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4213         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214   }
4215         
4216   pic16_genMult32X32_32(left, right,result);
4217 }
4218
4219
4220
4221 /*-----------------------------------------------------------------*/
4222 /* genMult - generates code for multiplication                     */
4223 /*-----------------------------------------------------------------*/
4224 static void genMult (iCode *ic)
4225 {
4226   operand *left = IC_LEFT(ic);
4227   operand *right = IC_RIGHT(ic);
4228   operand *result= IC_RESULT(ic);   
4229
4230     FENTRY;
4231         /* assign the amsops */
4232         pic16_aopOp (left,ic,FALSE);
4233         pic16_aopOp (right,ic,FALSE);
4234         pic16_aopOp (result,ic,TRUE);
4235
4236         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4237
4238         /* special cases first *
4239         * both are bits */
4240         if (AOP_TYPE(left) == AOP_CRY
4241                 && AOP_TYPE(right)== AOP_CRY) {
4242                 genMultbits(left,right,result);
4243           goto release ;
4244         }
4245
4246         /* if both are of size == 1 */
4247         if(AOP_SIZE(left) == 1
4248                 && AOP_SIZE(right) == 1) {
4249                 genMultOneByte(left,right,result);
4250           goto release ;
4251         }
4252
4253         /* if both are of size == 2 */
4254         if(AOP_SIZE(left) == 2
4255                 && AOP_SIZE(right) == 2) {
4256                 genMultOneWord(left, right, result);
4257           goto release;
4258         }
4259         
4260         /* if both are of size == 4 */
4261         if(AOP_SIZE(left) == 4
4262                 && AOP_SIZE(right) == 4) {
4263                 genMultOneLong(left, right, result);
4264           goto release;
4265         }
4266         
4267         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4268
4269
4270         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4271         /* should have been converted to function call */
4272         assert(0) ;
4273
4274 release :
4275         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4276         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4277         pic16_freeAsmop(result,NULL,ic,TRUE); 
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* genDivbits :- division of bits                                  */
4282 /*-----------------------------------------------------------------*/
4283 static void genDivbits (operand *left, 
4284                         operand *right, 
4285                         operand *result)
4286 {
4287   char *l;
4288
4289     FENTRY;
4290     /* the result must be bit */    
4291     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4292     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4293
4294     MOVA(l);    
4295
4296     pic16_emitcode("div","ab");
4297     pic16_emitcode("rrc","a");
4298     pic16_aopPut(AOP(result),"c",0);
4299 }
4300
4301 /*-----------------------------------------------------------------*/
4302 /* genDivOneByte : 8 bit division                                  */
4303 /*-----------------------------------------------------------------*/
4304 static void genDivOneByte (operand *left,
4305                            operand *right,
4306                            operand *result)
4307 {
4308   sym_link *opetype = operandType(result);
4309   char *l ;
4310   symbol *lbl ;
4311   int size,offset;
4312
4313         /* result = divident / divisor
4314          * - divident may be a register or a literal,
4315          * - divisor may be a register or a literal,
4316          * so there are 3 cases (literal / literal is optimized
4317          * by the front-end) to handle.
4318          * In addition we must handle signed and unsigned, which
4319          * result in 6 final different cases -- VR */
4320
4321     FENTRY;
4322     
4323     size = AOP_SIZE(result) - 1;
4324     offset = 1;
4325     /* signed or unsigned */
4326     if (SPEC_USIGN(opetype)) {
4327       pCodeOp *pct1,    /* count */
4328                 *pct2,  /* reste */
4329                 *pct3;  /* temp */
4330       symbol *label1, *label2, *label3;;
4331
4332
4333         /* unsigned is easy */
4334
4335         pct1 = pic16_popGetTempReg(1);
4336         pct2 = pic16_popGetTempReg(1);
4337         pct3 = pic16_popGetTempReg(1);
4338         
4339         label1 = newiTempLabel(NULL);
4340         label2 = newiTempLabel(NULL);
4341         label3 = newiTempLabel(NULL);
4342
4343         /* the following algorithm is extracted from divuint.c */
4344
4345         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4346         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4347         
4348         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4349
4350         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4351         
4352         pic16_emitpLabel(label1->key);
4353         
4354         emitCLRC;
4355         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4356
4357
4358         emitCLRC;
4359         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4360         
4361
4362         emitSKPNC;
4363         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4364         
4365         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4366         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4367         
4368         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4369         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4370         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4371         
4372         pic16_emitpLabel( label3->key );
4373         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4374         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4375         
4376         
4377
4378         pic16_emitpLabel(label2->key);
4379         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4380         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4381         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4382         
4383         /* result is in wreg */
4384         if(AOP_TYPE(result) != AOP_ACC)
4385                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4386
4387         pic16_popReleaseTempReg( pct3, 1);
4388         pic16_popReleaseTempReg( pct2, 1);
4389         pic16_popReleaseTempReg( pct1, 1);
4390
4391         return ;
4392     }
4393
4394     /* signed is a little bit more difficult */
4395
4396     /* save the signs of the operands */
4397     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4398     MOVA(l);    
4399     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4400     pic16_emitcode("push","acc"); /* save it on the stack */
4401
4402     /* now sign adjust for both left & right */
4403     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4404     MOVA(l);       
4405     lbl = newiTempLabel(NULL);
4406     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4407     pic16_emitcode("cpl","a");   
4408     pic16_emitcode("inc","a");
4409     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4410     pic16_emitcode("mov","b,a");
4411
4412     /* sign adjust left side */
4413     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4414     MOVA(l);
4415
4416     lbl = newiTempLabel(NULL);
4417     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4418     pic16_emitcode("cpl","a");
4419     pic16_emitcode("inc","a");
4420     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4421
4422     /* now the division */
4423     pic16_emitcode("div","ab");
4424     /* we are interested in the lower order
4425     only */
4426     pic16_emitcode("mov","b,a");
4427     lbl = newiTempLabel(NULL);
4428     pic16_emitcode("pop","acc");   
4429     /* if there was an over flow we don't 
4430     adjust the sign of the result */
4431     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4432     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4433     CLRC;
4434     pic16_emitcode("clr","a");
4435     pic16_emitcode("subb","a,b");
4436     pic16_emitcode("mov","b,a");
4437     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4438
4439     /* now we are done */
4440     pic16_aopPut(AOP(result),"b",0);
4441     if(size > 0){
4442         pic16_emitcode("mov","c,b.7");
4443         pic16_emitcode("subb","a,acc");   
4444     }
4445     while (size--)
4446         pic16_aopPut(AOP(result),"a",offset++);
4447
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genDiv - generates code for division                            */
4452 /*-----------------------------------------------------------------*/
4453 static void genDiv (iCode *ic)
4454 {
4455     operand *left = IC_LEFT(ic);
4456     operand *right = IC_RIGHT(ic);
4457     operand *result= IC_RESULT(ic);   
4458
4459
4460         /* Division is a very lengthy algorithm, so it is better
4461          * to call support routines than inlining algorithm.
4462          * Division functions written here just in case someone
4463          * wants to inline and not use the support libraries -- VR */
4464
4465     FENTRY;
4466     
4467     /* assign the amsops */
4468     pic16_aopOp (left,ic,FALSE);
4469     pic16_aopOp (right,ic,FALSE);
4470     pic16_aopOp (result,ic,TRUE);
4471
4472     /* special cases first */
4473     /* both are bits */
4474     if (AOP_TYPE(left) == AOP_CRY &&
4475         AOP_TYPE(right)== AOP_CRY) {
4476         genDivbits(left,right,result);
4477         goto release ;
4478     }
4479
4480     /* if both are of size == 1 */
4481     if (AOP_SIZE(left) == 1 &&
4482         AOP_SIZE(right) == 1 ) {
4483         genDivOneByte(left,right,result);
4484         goto release ;
4485     }
4486
4487     /* should have been converted to function call */
4488     assert(0);
4489 release :
4490     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4491     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492     pic16_freeAsmop(result,NULL,ic,TRUE); 
4493 }
4494
4495 /*-----------------------------------------------------------------*/
4496 /* genModbits :- modulus of bits                                   */
4497 /*-----------------------------------------------------------------*/
4498 static void genModbits (operand *left, 
4499                         operand *right, 
4500                         operand *result)
4501 {
4502   char *l;
4503
4504     FENTRY;  
4505     
4506     werror(W_POSSBUG2, __FILE__, __LINE__);
4507     /* the result must be bit */    
4508     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4509     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4510
4511     MOVA(l);       
4512
4513     pic16_emitcode("div","ab");
4514     pic16_emitcode("mov","a,b");
4515     pic16_emitcode("rrc","a");
4516     pic16_aopPut(AOP(result),"c",0);
4517 }
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genModOneByte : 8 bit modulus                                   */
4521 /*-----------------------------------------------------------------*/
4522 static void genModOneByte (operand *left,
4523                            operand *right,
4524                            operand *result)
4525 {
4526   sym_link *opetype = operandType(result);
4527   char *l ;
4528   symbol *lbl ;
4529
4530     FENTRY;
4531     werror(W_POSSBUG2, __FILE__, __LINE__);
4532
4533     /* signed or unsigned */
4534     if (SPEC_USIGN(opetype)) {
4535         /* unsigned is easy */
4536         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4537         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4538         MOVA(l);    
4539         pic16_emitcode("div","ab");
4540         pic16_aopPut(AOP(result),"b",0);
4541         return ;
4542     }
4543
4544     /* signed is a little bit more difficult */
4545
4546     /* save the signs of the operands */
4547     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4548     MOVA(l);
4549
4550     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4551     pic16_emitcode("push","acc"); /* save it on the stack */
4552
4553     /* now sign adjust for both left & right */
4554     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4555     MOVA(l);
4556
4557     lbl = newiTempLabel(NULL);
4558     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4559     pic16_emitcode("cpl","a");   
4560     pic16_emitcode("inc","a");
4561     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4562     pic16_emitcode("mov","b,a"); 
4563
4564     /* sign adjust left side */
4565     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4566     MOVA(l);
4567
4568     lbl = newiTempLabel(NULL);
4569     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4570     pic16_emitcode("cpl","a");   
4571     pic16_emitcode("inc","a");
4572     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4573
4574     /* now the multiplication */
4575     pic16_emitcode("div","ab");
4576     /* we are interested in the lower order
4577     only */
4578     lbl = newiTempLabel(NULL);
4579     pic16_emitcode("pop","acc");   
4580     /* if there was an over flow we don't 
4581     adjust the sign of the result */
4582     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4583     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4584     CLRC ;
4585     pic16_emitcode("clr","a");
4586     pic16_emitcode("subb","a,b");
4587     pic16_emitcode("mov","b,a");
4588     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4589
4590     /* now we are done */
4591     pic16_aopPut(AOP(result),"b",0);
4592
4593 }
4594
4595 /*-----------------------------------------------------------------*/
4596 /* genMod - generates code for division                            */
4597 /*-----------------------------------------------------------------*/
4598 static void genMod (iCode *ic)
4599 {
4600   operand *left = IC_LEFT(ic);
4601   operand *right = IC_RIGHT(ic);
4602   operand *result= IC_RESULT(ic);  
4603
4604     FENTRY;
4605     
4606     /* assign the amsops */
4607     pic16_aopOp (left,ic,FALSE);
4608     pic16_aopOp (right,ic,FALSE);
4609     pic16_aopOp (result,ic,TRUE);
4610
4611     /* special cases first */
4612     /* both are bits */
4613     if (AOP_TYPE(left) == AOP_CRY &&
4614         AOP_TYPE(right)== AOP_CRY) {
4615         genModbits(left,right,result);
4616         goto release ;
4617     }
4618
4619     /* if both are of size == 1 */
4620     if (AOP_SIZE(left) == 1 &&
4621         AOP_SIZE(right) == 1 ) {
4622         genModOneByte(left,right,result);
4623         goto release ;
4624     }
4625
4626     /* should have been converted to function call */
4627     assert(0);
4628
4629 release :
4630     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4631     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4632     pic16_freeAsmop(result,NULL,ic,TRUE); 
4633 }
4634
4635 /*-----------------------------------------------------------------*/
4636 /* genIfxJump :- will create a jump depending on the ifx           */
4637 /*-----------------------------------------------------------------*/
4638 /*
4639   note: May need to add parameter to indicate when a variable is in bit space.
4640 */
4641 static void genIfxJump (iCode *ic, char *jval)
4642 {
4643   FENTRY;
4644   
4645     /* if true label then we jump if condition
4646     supplied is true */
4647     if ( IC_TRUE(ic) ) {
4648
4649         if(strcmp(jval,"a") == 0)
4650           emitSKPZ;
4651         else if (strcmp(jval,"c") == 0)
4652           emitSKPNC;
4653         else {
4654           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4655           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4656         }
4657
4658         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4659         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4660
4661     }
4662     else {
4663         /* false label is present */
4664         if(strcmp(jval,"a") == 0)
4665           emitSKPNZ;
4666         else if (strcmp(jval,"c") == 0)
4667           emitSKPC;
4668         else {
4669           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4670           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4671         }
4672
4673         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4674         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4675
4676     }
4677
4678
4679     /* mark the icode as generated */
4680     ic->generated = 1;
4681 }
4682
4683 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4684 {
4685   FENTRY;
4686   
4687     /* if true label then we jump if condition
4688     supplied is true */
4689     if ( IC_TRUE(ic) ) {
4690       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4691       pic16_emitpcode(POC_BTFSC, jop);
4692
4693       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4694       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4695
4696     } else {
4697       /* false label is present */
4698       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4699       pic16_emitpcode(POC_BTFSS, jop);
4700           
4701       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4702       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4703     }
4704
4705
4706     /* mark the icode as generated */
4707     ic->generated = 1;
4708 }
4709
4710 #if 0
4711 // not needed ATM
4712
4713 /*-----------------------------------------------------------------*/
4714 /* genSkip                                                         */
4715 /*-----------------------------------------------------------------*/
4716 static void genSkip(iCode *ifx,int status_bit)
4717 {
4718   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4719   if(!ifx)
4720     return;
4721
4722   if ( IC_TRUE(ifx) ) {
4723     switch(status_bit) {
4724     case 'z':
4725       emitSKPNZ;
4726       break;
4727
4728     case 'c':
4729       emitSKPNC;
4730       break;
4731
4732     case 'd':
4733       emitSKPDC;
4734       break;
4735
4736     }
4737
4738     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4739     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4740
4741   } else {
4742
4743     switch(status_bit) {
4744
4745     case 'z':
4746       emitSKPZ;
4747       break;
4748
4749     case 'c':
4750       emitSKPC;
4751       break;
4752
4753     case 'd':
4754       emitSKPDC;
4755       break;
4756     }
4757     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4758     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4759
4760   }
4761
4762 }
4763 #endif
4764
4765 /*-----------------------------------------------------------------*/
4766 /* genSkipc                                                        */
4767 /*-----------------------------------------------------------------*/
4768 static void genSkipc(resolvedIfx *rifx)
4769 {
4770   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4771   
4772   if(!rifx)
4773     return;
4774
4775   if(rifx->condition)
4776     emitSKPC;
4777   else
4778     emitSKPNC;
4779
4780   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4781   rifx->generated = 1;
4782 }
4783
4784 #if !(USE_SIMPLE_GENCMP)
4785 /*-----------------------------------------------------------------*/
4786 /* genSkipz2                                                       */
4787 /*-----------------------------------------------------------------*/
4788 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4789 {
4790   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4791   
4792   if(!rifx)
4793     return;
4794
4795   if( (rifx->condition ^ invert_condition) & 1)
4796     emitSKPZ;
4797   else
4798     emitSKPNZ;
4799
4800   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4801   rifx->generated = 1;
4802 }
4803 #endif
4804
4805 #if 0
4806 /*-----------------------------------------------------------------*/
4807 /* genSkipz                                                        */
4808 /*-----------------------------------------------------------------*/
4809 static void genSkipz(iCode *ifx, int condition)
4810 {
4811   if(!ifx)
4812     return;
4813
4814   if(condition)
4815     emitSKPNZ;
4816   else
4817     emitSKPZ;
4818
4819   if ( IC_TRUE(ifx) )
4820     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4821   else
4822     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4823
4824   if ( IC_TRUE(ifx) )
4825     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4826   else
4827     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4828
4829 }
4830 #endif
4831
4832 #if !(USE_SIMPLE_GENCMP)
4833 /*-----------------------------------------------------------------*/
4834 /* genSkipCond                                                     */
4835 /*-----------------------------------------------------------------*/
4836 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4837 {
4838   if(!rifx)
4839     return;
4840
4841   if(rifx->condition)
4842     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4843   else
4844     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4845
4846
4847   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4848   rifx->generated = 1;
4849 }
4850 #endif
4851
4852 #if 0
4853 /*-----------------------------------------------------------------*/
4854 /* genChkZeroes :- greater or less than comparison                 */
4855 /*     For each byte in a literal that is zero, inclusive or the   */
4856 /*     the corresponding byte in the operand with W                */
4857 /*     returns true if any of the bytes are zero                   */
4858 /*-----------------------------------------------------------------*/
4859 static int genChkZeroes(operand *op, int lit,  int size)
4860 {
4861
4862   int i;
4863   int flag =1;
4864
4865   while(size--) {
4866     i = (lit >> (size*8)) & 0xff;
4867
4868     if(i==0) {
4869       if(flag) 
4870         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4871       else
4872         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4873       flag = 0;
4874     }
4875   }
4876
4877   return (flag==0);
4878 }
4879 #endif
4880
4881 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4882 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4883 #endif
4884 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4885 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4886
4887 /*-----------------------------------------------------------------*/
4888 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4889 /*                  aop (if it's NOT a literal) or from lit (if    */
4890 /*                  aop is a literal)                              */
4891 /*-----------------------------------------------------------------*/
4892 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4893   if (aop->type == AOP_LIT) {
4894     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4895   } else {
4896     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4897   }
4898 }
4899
4900 /*-----------------------------------------------------------------*/
4901 /* genCmp :- greater or less than comparison                       */
4902 /*-----------------------------------------------------------------*/
4903
4904 #if USE_SIMPLE_GENCMP
4905
4906 /* genCmp performs a left < right comparison, stores
4907  * the outcome in result (if != NULL) and generates
4908  * control flow code for the ifx (if != NULL).
4909  *
4910  * This version leaves in sequences like
4911  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4912  * which should be optmized by the peephole
4913  * optimizer - RN 2005-01-01 */
4914 static void genCmp (operand *left,operand *right,
4915                     operand *result, iCode *ifx, int sign)
4916 {
4917   resolvedIfx rIfx;
4918   int size;
4919   int offs;
4920   symbol *templbl;
4921   operand *dummy;
4922   unsigned long lit;
4923   unsigned long mask;
4924   int performedLt;
4925
4926   FENTRY;
4927   
4928   assert (AOP_SIZE(left) == AOP_SIZE(right));
4929   assert (left && right);
4930
4931   size = AOP_SIZE(right) - 1;
4932   mask = (0x100UL << (size*8)) - 1;
4933   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4934   performedLt = 1;
4935   templbl = NULL;
4936   lit = 0;
4937   
4938   resolveIfx (&rIfx, ifx);
4939
4940   /**********************************************************************
4941    * handle bits - bit compares are promoted to int compares seemingly! *
4942    **********************************************************************/
4943 #if 0
4944   // THIS IS COMPLETELY UNTESTED!
4945   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4946     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4947     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4948     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4949
4950     emitSETC;
4951     // 1 < {0,1} is false --> clear C by skipping the next instruction
4952     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4953     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4954     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4955     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4956     emitCLRC; // only skipped for left=0 && right=1
4957
4958     goto correct_result_in_carry;
4959   } // if
4960 #endif
4961
4962   /*************************************************
4963    * make sure that left is register (or the like) *
4964    *************************************************/
4965   if (!isAOP_REGlike(left)) {
4966     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4967     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4968     #endif
4969     assert (isAOP_LIT(left));
4970     assert (isAOP_REGlike(right));
4971     // swap left and right
4972     // left < right <==> right > left <==> (right >= left + 1)
4973     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4974
4975     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4976       // MAXVALUE < right? always false
4977       if (performedLt) emitCLRC; else emitSETC;
4978       goto correct_result_in_carry;
4979     } // if
4980
4981     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4982     // that's we handled it above.
4983     lit++;
4984
4985     dummy = left;
4986     left = right;
4987     right = dummy;
4988
4989     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4990   } else if (isAOP_LIT(right)) {
4991     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4992   } // if
4993
4994   assert (isAOP_REGlike(left)); // left must be register or the like
4995   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4996
4997   /*************************************************
4998    * special cases go here                         *
4999    *************************************************/
5000
5001   if (isAOP_LIT(right)) {
5002     if (!sign) {
5003       // unsigned comparison to a literal
5004       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5005       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5006       #endif
5007       if (lit == 0) {
5008         // unsigned left < 0? always false
5009         if (performedLt) emitCLRC; else emitSETC;
5010         goto correct_result_in_carry;
5011       }
5012     } else {
5013       // signed comparison to a literal
5014       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5015       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5016       #endif
5017       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5018         // signed left < 0x80000000? always false
5019         if (performedLt) emitCLRC; else emitSETC;
5020         goto correct_result_in_carry;
5021       } else if (lit == 0) {
5022         // compare left < 0; set CARRY if SIGNBIT(left) is set
5023         if (performedLt) emitSETC; else emitCLRC;
5024         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5025         if (performedLt) emitCLRC; else emitSETC;
5026         goto correct_result_in_carry;
5027       }
5028     } // if (!sign)
5029   } // right is literal
5030
5031   /*************************************************
5032    * perform a general case comparison             *
5033    * make sure we get CARRY==1 <==> left >= right  *
5034    *************************************************/
5035   // compare most significant bytes
5036   //DEBUGpc ("comparing bytes at offset %d", size);
5037   if (!sign) {
5038     // unsigned comparison
5039     mov2w_regOrLit (AOP(right), lit, size);
5040     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5041   } else {
5042     // signed comparison
5043     // (add 2^n to both operands then perform an unsigned comparison)
5044     if (isAOP_LIT(right)) {
5045       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5046       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5047
5048       if (litbyte == 0x80) {
5049         // left >= 0x80 -- always true, but more bytes to come
5050         pic16_mov2w (AOP(left), size);
5051         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5052         emitSETC;
5053       } else {
5054         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5055         pic16_mov2w (AOP(left), size);
5056         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5057         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5058       } // if
5059     } else {
5060       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5061       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5062       pic16_mov2w (AOP(left), size);
5063       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5064       pic16_emitpcode (POC_MOVWF, pctemp);
5065       pic16_mov2w (AOP(right), size);
5066       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5067       pic16_emitpcode (POC_SUBFW, pctemp);
5068       //pic16_popReleaseTempReg(pctemp, 1);
5069     }
5070   } // if (!sign)
5071
5072   // compare remaining bytes (treat as unsigned case from above)
5073   templbl = newiTempLabel ( NULL );
5074   offs = size;
5075   while (offs--) {
5076     //DEBUGpc ("comparing bytes at offset %d", offs);
5077     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5078     mov2w_regOrLit (AOP(right), lit, offs);
5079     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5080   } // while (offs)
5081   pic16_emitpLabel (templbl->key);
5082   goto result_in_carry;
5083
5084 result_in_carry:
5085   
5086   /****************************************************
5087    * now CARRY contains the result of the comparison: *
5088    * SUBWF sets CARRY iff                             *
5089    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5090    * (F=left, W=right)
5091    ****************************************************/
5092
5093   if (performedLt) {
5094     if (result && AOP_TYPE(result) != AOP_CRY) {
5095       // value will be stored
5096       emitTOGC;
5097     } else {
5098       // value wil only be used in the following genSkipc()
5099       rIfx.condition ^= 1;
5100     }
5101   } // if
5102
5103 correct_result_in_carry:
5104
5105   // assign result to variable (if neccessary)
5106   if (result && AOP_TYPE(result) != AOP_CRY) {
5107     //DEBUGpc ("assign result");
5108     size = AOP_SIZE(result);
5109     while (size--) {
5110       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5111     } // while
5112     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5113   } // if (result)
5114
5115   // perform conditional jump
5116   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5117   if (ifx) {
5118     //DEBUGpc ("generate control flow");
5119     rIfx.condition ^= 1;
5120     genSkipc (&rIfx);
5121     ifx->generated = 1;
5122   } // if
5123 }
5124
5125 #elif 1
5126                 /* { */
5127       /* original code */
5128 static void genCmp (operand *left,operand *right,
5129                     operand *result, iCode *ifx, int sign)
5130 {
5131   int size; //, offset = 0 ;
5132   unsigned long lit = 0L,i = 0;
5133   resolvedIfx rFalseIfx;
5134   //  resolvedIfx rTrueIfx;
5135   symbol *truelbl;
5136   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5137 /*
5138   if(ifx) {
5139     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5140     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5141   }
5142 */
5143
5144   FENTRY;
5145   
5146   resolveIfx(&rFalseIfx,ifx);
5147   truelbl  = newiTempLabel(NULL);
5148   size = max(AOP_SIZE(left),AOP_SIZE(right));
5149
5150   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5151
5152 #define _swapp
5153
5154   /* if literal is on the right then swap with left */
5155   if ((AOP_TYPE(right) == AOP_LIT)) {
5156     operand *tmp = right ;
5157     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5158     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5159 #ifdef _swapp
5160
5161     lit = (lit - 1) & mask;
5162     right = left;
5163     left = tmp;
5164     rFalseIfx.condition ^= 1;
5165 #endif
5166
5167   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5168     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5169   }
5170
5171
5172   //if(IC_TRUE(ifx) == NULL)
5173   /* if left & right are bit variables */
5174   if (AOP_TYPE(left) == AOP_CRY &&
5175       AOP_TYPE(right) == AOP_CRY ) {
5176     assert (0 && "bit variables used in genCmp");
5177     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5178     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5179   } else {
5180     /* subtract right from left if at the
5181        end the carry flag is set then we know that
5182        left is greater than right */
5183
5184     symbol *lbl  = newiTempLabel(NULL);
5185
5186 #if 0
5187         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5188                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5189 #endif
5190
5191 #ifndef _swapp
5192     if(AOP_TYPE(right) == AOP_LIT) {
5193
5194       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5195
5196       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5197
5198       /* special cases */
5199
5200       if(lit == 0) {
5201
5202         if(sign != 0) 
5203           genSkipCond(&rFalseIfx,left,size-1,7);
5204         else 
5205           /* no need to compare to 0...*/
5206           /* NOTE: this is a de-generate compare that most certainly 
5207            *       creates some dead code. */
5208           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5209
5210         if(ifx) ifx->generated = 1;
5211         return;
5212
5213       }
5214       size--;
5215
5216       if(size == 0) {
5217         //i = (lit >> (size*8)) & 0xff;
5218         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5219         
5220         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5221
5222         i = ((0-lit) & 0xff);
5223         if(sign) {
5224           if( i == 0x81) { 
5225             /* lit is 0x7f, all signed chars are less than
5226              * this except for 0x7f itself */
5227             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5228             genSkipz2(&rFalseIfx,0);
5229           } else {
5230             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5231             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5232             genSkipc(&rFalseIfx);
5233           }
5234
5235         } else {
5236           if(lit == 1) {
5237             genSkipz2(&rFalseIfx,1);
5238           } else {
5239             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5240             genSkipc(&rFalseIfx);
5241           }
5242         }
5243
5244         if(ifx) ifx->generated = 1;
5245         return;
5246       }
5247
5248       /* chars are out of the way. now do ints and longs */
5249
5250
5251       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5252         
5253       /* special cases */
5254
5255       if(sign) {
5256
5257         if(lit == 0) {
5258           genSkipCond(&rFalseIfx,left,size,7);
5259           if(ifx) ifx->generated = 1;
5260           return;
5261         }
5262
5263         if(lit <0x100) {
5264           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5265
5266           //rFalseIfx.condition ^= 1;
5267           //genSkipCond(&rFalseIfx,left,size,7);
5268           //rFalseIfx.condition ^= 1;
5269
5270           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5271           if(rFalseIfx.condition)
5272             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5273           else
5274             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5275
5276           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5277           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5278           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5279
5280           while(size > 1)
5281             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5282
5283           if(rFalseIfx.condition) {
5284             emitSKPZ;
5285             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5286
5287           } else {
5288             emitSKPNZ;
5289           }
5290
5291           genSkipc(&rFalseIfx);
5292           pic16_emitpLabel(truelbl->key);
5293           if(ifx) ifx->generated = 1;
5294           return;
5295
5296         }
5297
5298         if(size == 1) {
5299
5300           if( (lit & 0xff) == 0) {
5301             /* lower byte is zero */
5302             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5303             i = ((lit >> 8) & 0xff) ^0x80;
5304             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5305             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5306             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5307             genSkipc(&rFalseIfx);
5308
5309
5310             if(ifx) ifx->generated = 1;
5311             return;
5312
5313           }
5314         } else {
5315           /* Special cases for signed longs */
5316           if( (lit & 0xffffff) == 0) {
5317             /* lower byte is zero */
5318             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5319             i = ((lit >> 8*3) & 0xff) ^0x80;
5320             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5321             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5322             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5323             genSkipc(&rFalseIfx);
5324
5325
5326             if(ifx) ifx->generated = 1;
5327             return;
5328
5329           }
5330
5331         }
5332
5333
5334         if(lit & (0x80 << (size*8))) {
5335           /* lit is negative */
5336           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5337
5338           //genSkipCond(&rFalseIfx,left,size,7);
5339
5340           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5341
5342           if(rFalseIfx.condition)
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344           else
5345             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5346
5347
5348         } else {
5349           /* lit is positive */
5350           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5351           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5352           if(rFalseIfx.condition)
5353             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5354           else
5355             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5356
5357         }
5358
5359         /*
5360           This works, but is only good for ints.
5361           It also requires a "known zero" register.
5362           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5363           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5364           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5365           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5366           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5367           genSkipc(&rFalseIfx);
5368
5369           pic16_emitpLabel(truelbl->key);
5370           if(ifx) ifx->generated = 1;
5371           return;
5372         **/
5373           
5374         /* There are no more special cases, so perform a general compare */
5375   
5376         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5377         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5378
5379         while(size--) {
5380
5381           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5382           emitSKPNZ;
5383           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5384         }
5385         //rFalseIfx.condition ^= 1;
5386         genSkipc(&rFalseIfx);
5387
5388         pic16_emitpLabel(truelbl->key);
5389
5390         if(ifx) ifx->generated = 1;
5391         return;
5392
5393
5394       }
5395
5396
5397       /* sign is out of the way. So now do an unsigned compare */
5398       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5399
5400
5401       /* General case - compare to an unsigned literal on the right.*/
5402
5403       i = (lit >> (size*8)) & 0xff;
5404       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5405       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5406       while(size--) {
5407         i = (lit >> (size*8)) & 0xff;
5408
5409         if(i) {
5410           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5411           emitSKPNZ;
5412           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5413         } else {
5414           /* this byte of the lit is zero, 
5415            *if it's not the last then OR in the variable */
5416           if(size)
5417             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5418         }
5419       }
5420
5421
5422       pic16_emitpLabel(lbl->key);
5423 //      pic16_emitpLabel(truelbl->key);
5424       //if(emitFinalCheck)
5425       genSkipc(&rFalseIfx);
5426       if(sign)
5427         pic16_emitpLabel(truelbl->key);
5428
5429       if(ifx) ifx->generated = 1;
5430       return;
5431
5432
5433     }
5434 #endif  // _swapp
5435
5436     if(AOP_TYPE(left) == AOP_LIT) {
5437       //symbol *lbl = newiTempLabel(NULL);
5438
5439       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5440
5441
5442       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5443
5444       /* Special cases */
5445       if((lit == 0) && (sign == 0)){
5446
5447         size--;
5448         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5449         while(size) 
5450           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5451
5452         genSkipz2(&rFalseIfx,0);
5453         if(ifx) ifx->generated = 1;
5454         return;
5455       }
5456
5457       if(size==1) {
5458         /* Special cases */
5459         lit &= 0xff;
5460         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5461           /* degenerate compare can never be true */
5462           if(rFalseIfx.condition == 0)
5463             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5464
5465           if(ifx) ifx->generated = 1;
5466           return;
5467         }
5468
5469         if(sign) {
5470           /* signed comparisons to a literal byte */
5471
5472           int lp1 = (lit+1) & 0xff;
5473
5474           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5475           switch (lp1) {
5476           case 0:
5477             rFalseIfx.condition ^= 1;
5478             genSkipCond(&rFalseIfx,right,0,7);
5479             break;
5480           case 0x7f:
5481             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5482             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5483             genSkipz2(&rFalseIfx,1);
5484             break;
5485           default:
5486             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5487             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5488             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5489             rFalseIfx.condition ^= 1;
5490             genSkipc(&rFalseIfx);
5491             break;
5492           }
5493         } else {
5494           /* unsigned comparisons to a literal byte */
5495
5496           switch(lit & 0xff ) {
5497           case 0:
5498             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5499             genSkipz2(&rFalseIfx,0);
5500             break;
5501           case 0x7f:
5502             rFalseIfx.condition ^= 1;
5503             genSkipCond(&rFalseIfx,right,0,7);
5504             break;
5505
5506           default:
5507             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5508             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5509             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5510             rFalseIfx.condition ^= 1;
5511             if (AOP_TYPE(result) == AOP_CRY)
5512               genSkipc(&rFalseIfx);
5513             else {
5514               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5515               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5516             }         
5517             break;
5518           }
5519         }
5520
5521         if(ifx) ifx->generated = 1;
5522         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5523                 goto check_carry;
5524         return;
5525
5526       } else {
5527
5528         /* Size is greater than 1 */
5529
5530         if(sign) {
5531           int lp1 = lit+1;
5532
5533           size--;
5534
5535           if(lp1 == 0) {
5536             /* this means lit = 0xffffffff, or -1 */
5537
5538
5539             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5540             rFalseIfx.condition ^= 1;
5541             genSkipCond(&rFalseIfx,right,size,7);
5542             if(ifx) ifx->generated = 1;
5543
5544             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5545               goto check_carry;
5546
5547             return;
5548           }
5549
5550           if(lit == 0) {
5551             int s = size;
5552
5553             if(rFalseIfx.condition) {
5554               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5555               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5556             }
5557
5558             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5559             while(size--)
5560               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5561
5562
5563             emitSKPZ;
5564             if(rFalseIfx.condition) {
5565               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5566               pic16_emitpLabel(truelbl->key);
5567             }else {
5568               rFalseIfx.condition ^= 1;
5569               genSkipCond(&rFalseIfx,right,s,7);
5570             }
5571
5572             if(ifx) ifx->generated = 1;
5573
5574             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5575               goto check_carry;
5576
5577             return;
5578           }
5579
5580           if((size == 1) &&  (0 == (lp1&0xff))) {
5581             /* lower byte of signed word is zero */
5582             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5583             i = ((lp1 >> 8) & 0xff) ^0x80;
5584             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5585             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5586             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5587
5588             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5589               emitTOGC;
5590               if(ifx) ifx->generated = 1;
5591               goto check_carry;
5592             } else {
5593               rFalseIfx.condition ^= 1;
5594               genSkipc(&rFalseIfx);
5595               if(ifx) ifx->generated = 1;
5596             }
5597
5598             return;
5599           }
5600
5601           if(lit & (0x80 << (size*8))) {
5602             /* Lit is less than zero */
5603             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5604             //rFalseIfx.condition ^= 1;
5605             //genSkipCond(&rFalseIfx,left,size,7);
5606             //rFalseIfx.condition ^= 1;
5607             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5608             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5609
5610             if(rFalseIfx.condition)
5611               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5612             else
5613               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5614
5615
5616           } else {
5617             /* Lit is greater than or equal to zero */
5618             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5619             //rFalseIfx.condition ^= 1;
5620             //genSkipCond(&rFalseIfx,right,size,7);
5621             //rFalseIfx.condition ^= 1;
5622
5623             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5624             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5625
5626             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5627             if(rFalseIfx.condition)
5628               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5629             else
5630               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5631
5632           }
5633
5634           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5635           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5636
5637           while(size--) {
5638
5639             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5640             emitSKPNZ;
5641             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5642           }
5643           rFalseIfx.condition ^= 1;
5644           //rFalseIfx.condition = 1;
5645           genSkipc(&rFalseIfx);
5646
5647           pic16_emitpLabel(truelbl->key);
5648
5649           if(ifx) ifx->generated = 1;
5650
5651
5652           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5653             goto check_carry;
5654
5655           return;
5656           // end of if (sign)
5657         } else {
5658
5659           /* compare word or long to an unsigned literal on the right.*/
5660
5661
5662           size--;
5663           if(lit < 0xff) {
5664             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5665             switch (lit) {
5666             case 0:
5667               break; /* handled above */
5668 /*
5669             case 0xff:
5670               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5671               while(size--)
5672                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5673               genSkipz2(&rFalseIfx,0);
5674               break;
5675 */
5676             default:
5677               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5678               while(--size)
5679                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5680
5681               emitSKPZ;
5682               if(rFalseIfx.condition)
5683                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5684               else
5685                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5686
5687
5688               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5689               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5690
5691               rFalseIfx.condition ^= 1;
5692               genSkipc(&rFalseIfx);
5693             }
5694
5695             pic16_emitpLabel(truelbl->key);
5696
5697             if(ifx) ifx->generated = 1;
5698
5699             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5700               goto check_carry;
5701
5702             return;
5703           }
5704
5705
5706           lit++;
5707           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5708           i = (lit >> (size*8)) & 0xff;
5709
5710           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5711           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5712
5713           while(size--) {
5714             i = (lit >> (size*8)) & 0xff;
5715
5716             if(i) {
5717               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5718               emitSKPNZ;
5719               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5720             } else {
5721               /* this byte of the lit is zero, 
5722                * if it's not the last then OR in the variable */
5723               if(size)
5724                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5725             }
5726           }
5727
5728
5729           pic16_emitpLabel(lbl->key);
5730
5731           rFalseIfx.condition ^= 1;
5732
5733           genSkipc(&rFalseIfx);
5734         }
5735
5736         if(sign)
5737           pic16_emitpLabel(truelbl->key);
5738         if(ifx) ifx->generated = 1;
5739
5740             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5741               goto check_carry;
5742
5743         return;
5744       }
5745     }
5746     /* Compare two variables */
5747
5748     DEBUGpic16_emitcode(";sign","%d",sign);
5749
5750     size--;
5751     if(sign) {
5752       /* Sigh. thus sucks... */
5753       if(size) {
5754         pCodeOp *pctemp;
5755         
5756         pctemp = pic16_popGetTempReg(1);
5757         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5758         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5760         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5761         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5762         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5763         pic16_popReleaseTempReg(pctemp, 1);
5764       } else {
5765         /* Signed char comparison */
5766         /* Special thanks to Nikolai Golovchenko for this snippet */
5767         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5768         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5769         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5770         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5771         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5772         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5773
5774         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5775         genSkipc(&rFalseIfx);
5776           
5777         if(ifx) ifx->generated = 1;
5778
5779             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5780               goto check_carry;
5781
5782         return;
5783       }
5784
5785     } else {
5786
5787       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5788       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5789     }
5790
5791
5792     /* The rest of the bytes of a multi-byte compare */
5793     while (size) {
5794
5795       emitSKPZ;
5796       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5797       size--;
5798
5799       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5800       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5801
5802
5803     }
5804
5805     pic16_emitpLabel(lbl->key);
5806
5807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5808     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5809         (AOP_TYPE(result) == AOP_REG)) {
5810       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5811       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5812     } else {
5813       genSkipc(&rFalseIfx);
5814     }         
5815     //genSkipc(&rFalseIfx);
5816     if(ifx) ifx->generated = 1;
5817
5818
5819             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5820               goto check_carry;
5821
5822     return;
5823
5824   }
5825
5826 check_carry:
5827   if ((AOP_TYPE(result) != AOP_CRY) 
5828         && AOP_SIZE(result)) {
5829     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5830
5831     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5832
5833     pic16_outBitC(result);
5834   } else {
5835     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5836     /* if the result is used in the next
5837        ifx conditional branch then generate
5838        code a little differently */
5839     if (ifx )
5840       genIfxJump (ifx,"c");
5841     else
5842       pic16_outBitC(result);
5843     /* leave the result in acc */
5844   }
5845
5846 }
5847
5848 #else   /* old version of genCmp() */   /* } else { */
5849
5850 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5851 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5852         operand *result, int offset, int invert_op)
5853 {
5854   /* add code here */
5855   
5856   /* check condition, > or < ?? */
5857   if(rIfx->condition != 0)invert_op ^= 1;
5858   
5859   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5860
5861   if(!ifx)invert_op ^= 1;
5862
5863   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5864       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5865   
5866   /* do selection */
5867   if(!invert_op)return POC_CPFSGT;
5868   else return POC_CPFSLT;
5869 }
5870
5871 static int compareAopfirstpass=1;
5872
5873 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5874             operand *oper, int offset, operand *result,
5875             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5876             symbol *tlbl)
5877 {
5878   int op;
5879   symbol *truelbl;
5880
5881   /* invert if there is a result to be loaded, in order to fit,
5882    * SETC/CLRC sequence */
5883   if(AOP_SIZE(result))invert_op ^= 1;
5884
5885 //  if(sign && !offset)invert_op ^= 1;
5886   
5887 //  if(sign)invert_op ^= 1;
5888   
5889   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5890
5891   if(AOP_SIZE(result) && compareAopfirstpass) {
5892     if(!ifx) {
5893       if(pcop2)
5894         pic16_emitpcode(POC_SETF, pcop2);
5895       else
5896         emitSETC;
5897     } else {
5898       if(pcop2)
5899         pic16_emitpcode(POC_CLRF, pcop2);
5900       else
5901         emitCLRC;
5902     }
5903   }
5904
5905   compareAopfirstpass = 0;
5906
5907       /* there is a bug when comparing operands with size > 1,
5908        * because higher bytes can be equal and test should be performed
5909        * to the next lower byte, current algorithm, considers operands
5910        * inequal in these cases! -- VR 20041107 */
5911
5912     
5913   if(pcop)
5914     pic16_emitpcode(op, pcop);
5915   else
5916     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5917
5918
5919   if((!sign || !offset) && AOP_SIZE(result)) {
5920     if(!ifx) {
5921       if(pcop2)
5922         pic16_emitpcode(POC_CLRF, pcop2);
5923         else
5924         emitCLRC;
5925     } else {
5926       if(pcop2)
5927         pic16_emitpcode(POC_SETF, pcop2);
5928       else
5929         emitSETC;
5930     }
5931     
5932     /* don't emit final branch (offset == 0) */
5933     if(offset) {
5934
5935       if(pcop2)
5936         pic16_emitpcode(POC_RRCF, pcop2);
5937
5938       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5939     }
5940   } else {
5941     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5942       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5943             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5944
5945       truelbl = newiTempLabel( NULL );
5946       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5947       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5948         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5949       else
5950         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5951       pic16_emitpLabel(truelbl->key);
5952     } else {
5953       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5954     }
5955   }
5956 }
5957
5958
5959   
5960
5961 #if 1   /* { */
5962 static void genCmp (operand *left, operand *right,
5963                     operand *result, iCode *ifx, int sign)
5964 {
5965   int size, cmpop=1;
5966   long lit = 0L;
5967   resolvedIfx rFalseIfx;
5968   symbol *falselbl, *tlbl;
5969
5970     FENTRY;
5971     
5972     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5973
5974     resolveIfx(&rFalseIfx, ifx);
5975     size = max(AOP_SIZE(left), AOP_SIZE(right));
5976     
5977     /* if left & right are bit variables */
5978     if(AOP_TYPE(left) == AOP_CRY
5979       && AOP_TYPE(right) == AOP_CRY ) {
5980
5981         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5982         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5983         
5984         werror(W_POSSBUG2, __FILE__, __LINE__);
5985         exit(-1);
5986     }
5987     
5988     /* if literal is on the right then swap with left */
5989     if((AOP_TYPE(right) == AOP_LIT)) {
5990       operand *tmp = right ;
5991 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5992
5993         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5994
5995 //      lit = (lit - 1) & mask;
5996         right = left;
5997         left = tmp;
5998         rFalseIfx.condition ^= 1;               /* reverse compare */
5999     } else
6000     if ((AOP_TYPE(left) == AOP_LIT)) {
6001       /* float compares are handled by support functions */
6002       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6003     }
6004
6005     /* actual comparing algorithm */
6006 //    size = AOP_SIZE( right );
6007
6008     falselbl = newiTempLabel( NULL );
6009     if(AOP_TYPE(left) == AOP_LIT) {
6010       /* compare to literal */
6011       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6012       
6013       if(sign) {
6014         pCodeOp *pct, *pct2;
6015         symbol *tlbl1;
6016
6017         /* signed compare */
6018         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6019
6020         pct = pic16_popCopyReg(&pic16_pc_prodl);
6021         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6022         tlbl = newiTempLabel( NULL );
6023         
6024         /* first compare signs:
6025          *  a. if both are positive, compare just like unsigned
6026          *  b. if both are negative, invert cmpop, compare just like unsigned
6027          *  c. if different signs, determine the result directly */
6028
6029         size--;
6030
6031 #if 1
6032         /* { */
6033         tlbl1 = newiTempLabel( NULL );
6034 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6035
6036         if(lit > 0) {
6037
6038           /* literal is zero or positive:
6039            *  a. if carry is zero, too, continue compare,
6040            *  b. if carry is set, then continue depending on cmpop ^ condition:
6041            *    1. '<' return false (literal < variable),
6042            *    2. '>' return true (literal > variable) */
6043 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6044           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6045           
6046           
6047           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6049         } else 
6050         if(lit < 0) {
6051           
6052           /* literal is negative:
6053            *  a. if carry is set, too, continue compare,
6054            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6055            *    1. '<' return true (literal < variable),
6056            *    2. '>' return false (literal > variable) */
6057 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6058           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6059           
6060           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6061           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6062         }
6063 #if 1
6064         else {
6065           /* lit == 0 */
6066           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6067           
6068           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6069           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6070         }
6071 #endif
6072         
6073         
6074         pic16_emitpLabel( tlbl1->key );
6075 #endif  /* } */
6076
6077         compareAopfirstpass=1;
6078 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6079 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6080 //        pic16_emitpcode(POC_MOVWF, pct);
6081
6082 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6083         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6084 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6085         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6086
6087         /* generic case */        
6088           while( size-- ) {
6089 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6090 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6091 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6092 //            pic16_emitpcode(POC_MOVWF, pct);
6093
6094 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6095             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6096             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6097 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6098 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6099           }
6100 //        }
6101         
6102         if(ifx)ifx->generated = 1;
6103
6104         if(AOP_SIZE(result)) {
6105           pic16_emitpLabel(tlbl->key);
6106           pic16_emitpLabel(falselbl->key);
6107           pic16_outBitOp( result, pct2 );
6108         } else {
6109           pic16_emitpLabel(tlbl->key);
6110         }
6111       } else {
6112
6113
6114         /* unsigned compare */      
6115         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6116     
6117         compareAopfirstpass=1;
6118         while(size--) {
6119           
6120           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6121           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6122
6123         }
6124
6125         if(ifx)ifx->generated = 1;
6126
6127
6128         if(AOP_SIZE(result)) {
6129           pic16_emitpLabel(falselbl->key);
6130           pic16_outBitC( result );
6131         }
6132
6133       }
6134     } else {
6135       /* compare registers */
6136       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6137
6138
6139       if(sign) {
6140         pCodeOp *pct, *pct2;
6141         
6142         /* signed compare */
6143         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6144
6145         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6146         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6147         tlbl = newiTempLabel( NULL );
6148         
6149         compareAopfirstpass=1;
6150
6151         size--;
6152         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6153 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6155         pic16_emitpcode(POC_MOVWF, pct);
6156
6157         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6159         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6160
6161         /* WREG already holds left + 0x80 */
6162         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6163         
6164         while( size-- ) {
6165           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6166 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6167           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6168           pic16_emitpcode(POC_MOVWF, pct);
6169                 
6170           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6171 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6172           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6173
6174           /* WREG already holds left + 0x80 */
6175           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6176 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6177         }
6178         
6179         if(ifx)ifx->generated = 1;
6180
6181         if(AOP_SIZE(result)) {
6182           pic16_emitpLabel(tlbl->key);
6183           pic16_emitpLabel(falselbl->key);
6184           pic16_outBitOp( result, pct2 );
6185         } else {
6186           pic16_emitpLabel(tlbl->key);
6187         }
6188
6189       } else {
6190         /* unsigned compare */      
6191         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6192
6193         compareAopfirstpass=1;
6194         while(size--) {
6195           
6196           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6197           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6198
6199         }
6200
6201         if(ifx)ifx->generated = 1;
6202         if(AOP_SIZE(result)) {
6203
6204           pic16_emitpLabel(falselbl->key);
6205           pic16_outBitC( result );
6206         }
6207
6208       }
6209     }
6210 }
6211
6212 #else    /* } else { */
6213
6214 /* new version of genCmp -- VR 20041012 */
6215 static void genCmp (operand *left,operand *right,
6216                     operand *result, iCode *ifx, int sign)
6217 {
6218   int size; //, offset = 0 ;
6219   unsigned long lit = 0L,i = 0;
6220   resolvedIfx rFalseIfx;
6221   int willCheckCarry=0;
6222   //  resolvedIfx rTrueIfx;
6223   symbol *truelbl;
6224
6225     FENTRY;
6226   
6227   /* General concept:
6228    * subtract right from left if at the end the carry flag is set then we
6229    * know that left is greater than right */
6230             
6231   resolveIfx(&rFalseIfx,ifx);
6232   truelbl  = newiTempLabel(NULL);
6233   size = max(AOP_SIZE(left),AOP_SIZE(right));
6234
6235   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6236
6237   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6238    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6239   
6240
6241   /* if literal is on the right then swap with left */
6242   if ((AOP_TYPE(right) == AOP_LIT)) {
6243     operand *tmp = right ;
6244     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6245
6246       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6247
6248 //      lit = (lit - 1) & mask;
6249       right = left;
6250       left = tmp;
6251       rFalseIfx.condition ^= 1;         /* reverse compare */
6252   } else
6253   if ((AOP_TYPE(left) == AOP_LIT)) {
6254     /* float compares are handled by support functions */
6255     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6256   }
6257
6258
6259   //if(IC_TRUE(ifx) == NULL)
6260   /* if left & right are bit variables */
6261   if (AOP_TYPE(left) == AOP_CRY &&
6262       AOP_TYPE(right) == AOP_CRY ) {
6263
6264     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6265     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6266
6267   } else {
6268     symbol *lbl  = newiTempLabel(NULL);
6269
6270     if(AOP_TYPE(left) == AOP_LIT) {
6271       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6272
6273       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6274         willCheckCarry = 1;
6275       else willCheckCarry = 0;
6276
6277       /* Special cases */
6278       if((lit == 0) && (sign == 0)) {
6279         /* unsigned compare to 0 */
6280         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6281         
6282         size--;
6283         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6284         while(size) 
6285           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6286
6287         genSkipz2(&rFalseIfx,0);
6288         if(ifx)ifx->generated = 1;
6289         return;
6290       }
6291
6292       if(size==1) {
6293         /* Special cases */
6294         lit &= 0xff;
6295         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6296           /* degenerate compare can never be true */
6297           if(rFalseIfx.condition == 0)
6298             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6299
6300           if(ifx) ifx->generated = 1;
6301           return;
6302         }
6303
6304         if(sign) {
6305           /* signed comparisons to a literal byte */
6306           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6307
6308           int lp1 = (lit+1) & 0xff;
6309
6310           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6311           switch (lp1) {
6312           case 0:
6313             rFalseIfx.condition ^= 1;
6314             genSkipCond(&rFalseIfx,right,0,7);
6315             break;
6316           case 0x7f:
6317             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6318             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6319             genSkipz2(&rFalseIfx,1);
6320             break;
6321           default:
6322             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6323             
6324             if(rFalseIfx.condition)
6325               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6326             else
6327               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6328
6329             if(willCheckCarry) {
6330               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6331               else { emitSETC; emitCLRC; }
6332               
6333             } else {
6334               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6335             }              
6336                       
6337 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6338             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6339             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6340             rFalseIfx.condition ^= 1;
6341             genSkipc(&rFalseIfx);
6342 */
6343             break;
6344           }
6345         } else {
6346           /* unsigned comparisons to a literal byte */
6347           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6348
6349           switch(lit & 0xff ) {
6350                           /* special cases */
6351           case 0:
6352             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6353             genSkipz2(&rFalseIfx,0);
6354             break;
6355           case 0x7f:
6356             rFalseIfx.condition ^= 1;
6357             genSkipCond(&rFalseIfx,right,0,7);
6358             break;
6359           default:
6360             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6361             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6362             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6363             rFalseIfx.condition ^= 1;
6364             if (AOP_TYPE(result) == AOP_CRY)
6365               genSkipc(&rFalseIfx);
6366             else {
6367               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6368               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6369             }         
6370             break;
6371           }
6372         }
6373
6374         if(ifx) ifx->generated = 1;
6375         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6376                 goto check_carry;
6377         return;
6378
6379       } else {
6380
6381         /* Size is greater than 1 */
6382
6383         if(sign) {
6384           int lp1 = lit+1;
6385
6386           size--;
6387
6388           if(lp1 == 0) {
6389             /* this means lit = 0xffffffff, or -1 */
6390
6391
6392             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6393             rFalseIfx.condition ^= 1;
6394             genSkipCond(&rFalseIfx,right,size,7);
6395             if(ifx) ifx->generated = 1;
6396             return;
6397           }
6398
6399           if(lit == 0) {
6400             int s = size;
6401
6402             if(rFalseIfx.condition) {
6403               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6404               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6405             }
6406
6407             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6408             while(size--)
6409               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6410
6411
6412             emitSKPZ;
6413             if(rFalseIfx.condition) {
6414               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6415               pic16_emitpLabel(truelbl->key);
6416             }else {
6417               rFalseIfx.condition ^= 1;
6418               genSkipCond(&rFalseIfx,right,s,7);
6419             }
6420
6421             if(ifx) ifx->generated = 1;
6422             return;
6423           }
6424
6425           if((size == 1) &&  (0 == (lp1&0xff))) {
6426             /* lower byte of signed word is zero */
6427             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6428             i = ((lp1 >> 8) & 0xff) ^0x80;
6429             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6430             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6431             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6432             rFalseIfx.condition ^= 1;
6433             genSkipc(&rFalseIfx);
6434
6435
6436             if(ifx) ifx->generated = 1;
6437             return;
6438           }
6439
6440           if(lit & (0x80 << (size*8))) {
6441             /* Lit is less than zero */
6442             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6443             //rFalseIfx.condition ^= 1;
6444             //genSkipCond(&rFalseIfx,left,size,7);
6445             //rFalseIfx.condition ^= 1;
6446             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6447             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6448
6449             if(rFalseIfx.condition)
6450               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6451             else
6452               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6453
6454
6455           } else {
6456             /* Lit is greater than or equal to zero */
6457             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6458             //rFalseIfx.condition ^= 1;
6459             //genSkipCond(&rFalseIfx,right,size,7);
6460             //rFalseIfx.condition ^= 1;
6461
6462             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6463             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6464
6465             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6466             if(rFalseIfx.condition)
6467               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6468             else
6469               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6470
6471           }
6472
6473
6474           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6475           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6476
6477           while(size--) {
6478
6479             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6480             emitSKPNZ;
6481             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6482           }
6483           rFalseIfx.condition ^= 1;
6484           //rFalseIfx.condition = 1;
6485           genSkipc(&rFalseIfx);
6486
6487           pic16_emitpLabel(truelbl->key);
6488
6489           if(ifx) ifx->generated = 1;
6490           return;
6491           // end of if (sign)
6492         } else {
6493
6494           /* compare word or long to an unsigned literal on the right.*/
6495
6496
6497           size--;
6498           if(lit < 0xff) {
6499             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6500             switch (lit) {
6501             case 0:
6502               break; /* handled above */
6503 /*
6504             case 0xff:
6505               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6506               while(size--)
6507                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6508               genSkipz2(&rFalseIfx,0);
6509               break;
6510 */
6511             default:
6512               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6513               while(--size)
6514                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6515
6516               emitSKPZ;
6517               if(rFalseIfx.condition)
6518                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6519               else
6520                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6521
6522
6523               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6524               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6525
6526               rFalseIfx.condition ^= 1;
6527               genSkipc(&rFalseIfx);
6528             }
6529
6530             pic16_emitpLabel(truelbl->key);
6531
6532             if(ifx) ifx->generated = 1;
6533             return;
6534           }
6535
6536
6537           lit++;
6538           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6539           i = (lit >> (size*8)) & 0xff;
6540
6541           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6542           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6543
6544           while(size--) {
6545             i = (lit >> (size*8)) & 0xff;
6546
6547             if(i) {
6548               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6549               emitSKPNZ;
6550               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6551             } else {
6552               /* this byte of the lit is zero, 
6553                * if it's not the last then OR in the variable */
6554               if(size)
6555                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6556             }
6557           }
6558
6559
6560           pic16_emitpLabel(lbl->key);
6561
6562           rFalseIfx.condition ^= 1;
6563
6564           genSkipc(&rFalseIfx);
6565         }
6566
6567         if(sign)
6568           pic16_emitpLabel(truelbl->key);
6569         if(ifx) ifx->generated = 1;
6570         return;
6571       }
6572     }
6573     /* Compare two variables */
6574
6575     DEBUGpic16_emitcode(";sign","%d",sign);
6576
6577     size--;
6578     if(sign) {
6579       /* Sigh. thus sucks... */
6580       if(size) {
6581         pCodeOp *pctemp;
6582         
6583         pctemp = pic16_popGetTempReg(1);
6584         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6585         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6587         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6588         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6589         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6590         pic16_popReleaseTempReg(pctemp, 1);
6591       } else {
6592         /* Signed char comparison */
6593         /* Special thanks to Nikolai Golovchenko for this snippet */
6594         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6595         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6596         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6597         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6598         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6599         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6600
6601         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6602         genSkipc(&rFalseIfx);
6603           
6604         if(ifx) ifx->generated = 1;
6605         return;
6606       }
6607
6608     } else {
6609
6610       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6611       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6612     }
6613
6614
6615     /* The rest of the bytes of a multi-byte compare */
6616     while (size) {
6617
6618       emitSKPZ;
6619       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6620       size--;
6621
6622       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6623       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6624
6625
6626     }
6627
6628     pic16_emitpLabel(lbl->key);
6629
6630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6631     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6632         (AOP_TYPE(result) == AOP_REG)) {
6633       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6634       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6635     } else {
6636       genSkipc(&rFalseIfx);
6637     }         
6638     //genSkipc(&rFalseIfx);
6639     if(ifx) ifx->generated = 1;
6640
6641     return;
6642
6643   }
6644
6645 check_carry:
6646   if ((AOP_TYPE(result) != AOP_CRY) 
6647         && AOP_SIZE(result)) {
6648     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6649
6650     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6651
6652     pic16_outBitC(result);
6653   } else {
6654     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6655     /* if the result is used in the next
6656        ifx conditional branch then generate
6657        code a little differently */
6658     if (ifx )
6659       genIfxJump (ifx,"c");
6660     else
6661       pic16_outBitC(result);
6662     /* leave the result in acc */
6663   }
6664
6665 }
6666 #endif  /* } */
6667
6668
6669 #endif  /* } */
6670
6671
6672
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpGt :- greater than comparison                             */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpGt (iCode *ic, iCode *ifx)
6677 {
6678   operand *left, *right, *result;
6679   sym_link *letype , *retype;
6680   int sign ;
6681
6682     FENTRY;
6683     
6684     left = IC_LEFT(ic);
6685     right= IC_RIGHT(ic);
6686     result = IC_RESULT(ic);
6687
6688     letype = getSpec(operandType(left));
6689     retype =getSpec(operandType(right));
6690     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6691     /* assign the amsops */
6692     pic16_aopOp (left,ic,FALSE);
6693     pic16_aopOp (right,ic,FALSE);
6694     pic16_aopOp (result,ic,TRUE);
6695
6696     genCmp(right, left, result, ifx, sign);
6697
6698     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6699     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6700     pic16_freeAsmop(result,NULL,ic,TRUE); 
6701 }
6702
6703 /*-----------------------------------------------------------------*/
6704 /* genCmpLt - less than comparisons                                */
6705 /*-----------------------------------------------------------------*/
6706 static void genCmpLt (iCode *ic, iCode *ifx)
6707 {
6708   operand *left, *right, *result;
6709   sym_link *letype , *retype;
6710   int sign ;
6711
6712     FENTRY;
6713
6714     left = IC_LEFT(ic);
6715     right= IC_RIGHT(ic);
6716     result = IC_RESULT(ic);
6717
6718     letype = getSpec(operandType(left));
6719     retype =getSpec(operandType(right));
6720     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6721
6722     /* assign the amsops */
6723     pic16_aopOp (left,ic,FALSE);
6724     pic16_aopOp (right,ic,FALSE);
6725     pic16_aopOp (result,ic,TRUE);
6726
6727     genCmp(left, right, result, ifx, sign);
6728
6729     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6730     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6731     pic16_freeAsmop(result,NULL,ic,TRUE); 
6732 }
6733
6734 #if 0
6735 // not needed ATM
6736 // FIXME reenable literal optimisation when the pic16 port is stable
6737
6738 /*-----------------------------------------------------------------*/
6739 /* genc16bit2lit - compare a 16 bit value to a literal             */
6740 /*-----------------------------------------------------------------*/
6741 static void genc16bit2lit(operand *op, int lit, int offset)
6742 {
6743   int i;
6744
6745   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6746   if( (lit&0xff) == 0) 
6747     i=1;
6748   else
6749     i=0;
6750
6751   switch( BYTEofLONG(lit,i)) { 
6752   case 0:
6753     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6754     break;
6755   case 1:
6756     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6757     break;
6758   case 0xff:
6759     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6760     break;
6761   default:
6762     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6763     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6764   }
6765
6766   i ^= 1;
6767
6768   switch( BYTEofLONG(lit,i)) { 
6769   case 0:
6770     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6771     break;
6772   case 1:
6773     emitSKPNZ;
6774     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6775     break;
6776   case 0xff:
6777     emitSKPNZ;
6778     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6779     break;
6780   default:
6781     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6782     emitSKPNZ;
6783     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6784
6785   }
6786
6787 }
6788 #endif
6789
6790 #if 0
6791 // not needed ATM
6792 /*-----------------------------------------------------------------*/
6793 /* gencjneshort - compare and jump if not equal                    */
6794 /*-----------------------------------------------------------------*/
6795 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6796 {
6797   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6798   int offset = 0;
6799   int res_offset = 0;  /* the result may be a different size then left or right */
6800   int res_size = AOP_SIZE(result);
6801   resolvedIfx rIfx;
6802   symbol *lbl, *lbl_done;
6803
6804   unsigned long lit = 0L;
6805   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6806
6807   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6808   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6809   if(result)
6810     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6811   resolveIfx(&rIfx,ifx);
6812   lbl =  newiTempLabel(NULL);
6813   lbl_done =  newiTempLabel(NULL);
6814
6815
6816   /* if the left side is a literal or 
6817      if the right is in a pointer register and left 
6818      is not */
6819   if ((AOP_TYPE(left) == AOP_LIT) || 
6820       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821     operand *t = right;
6822     right = left;
6823     left = t;
6824   }
6825   if(AOP_TYPE(right) == AOP_LIT)
6826     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6827
6828   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6829     preserve_result = 1;
6830
6831   if(result && !preserve_result)
6832     {
6833       int i;
6834       for(i = 0; i < AOP_SIZE(result); i++)
6835         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6836     }
6837
6838
6839   /* if the right side is a literal then anything goes */
6840   if (AOP_TYPE(right) == AOP_LIT &&
6841       AOP_TYPE(left) != AOP_DIR ) {
6842     switch(size) {
6843     case 2:
6844       genc16bit2lit(left, lit, 0);
6845       emitSKPZ;
6846       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6847       break;
6848     default:
6849       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6850       while (size--) {
6851         if(lit & 0xff) {
6852           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6853           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6854         } else {
6855           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6856         }
6857
6858         emitSKPZ;
6859         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6860         offset++;
6861         if(res_offset < res_size-1)
6862           res_offset++;
6863         lit >>= 8;
6864       }
6865       break;
6866     }
6867   }
6868
6869   /* if the right side is in a register or in direct space or
6870      if the left is a pointer register & right is not */    
6871   else if (AOP_TYPE(right) == AOP_REG ||
6872            AOP_TYPE(right) == AOP_DIR || 
6873            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6874            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6875     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6876     int lbl_key = lbl->key;
6877
6878     if(result) {
6879       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6880       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6881     }else {
6882       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6883       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6884               __FUNCTION__,__LINE__);
6885       return;
6886     }
6887    
6888 /*     switch(size) { */
6889 /*     case 2: */
6890 /*       genc16bit2lit(left, lit, 0); */
6891 /*       emitSKPNZ; */
6892 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6893 /*       break; */
6894 /*     default: */
6895     while (size--) {
6896       int emit_skip=1;
6897       if((AOP_TYPE(left) == AOP_DIR) && 
6898          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6899
6900         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6901         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6902
6903       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6904             
6905         switch (lit & 0xff) {
6906         case 0:
6907           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6908           break;
6909         case 1:
6910           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6911           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6912           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6913           emit_skip=0;
6914           break;
6915         case 0xff:
6916           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6917           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6918           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6919           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6920           emit_skip=0;
6921           break;
6922         default:
6923           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6924           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6925         }
6926         lit >>= 8;
6927
6928       } else {
6929         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6930       }
6931       if(emit_skip) {
6932         if(AOP_TYPE(result) == AOP_CRY) {
6933           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6934           if(rIfx.condition)
6935             emitSKPNZ;
6936           else
6937             emitSKPZ;
6938           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6939         } else {
6940           /* fix me. probably need to check result size too */
6941           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6942           if(rIfx.condition)
6943             emitSKPZ;
6944           else
6945             emitSKPNZ;
6946           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6947           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6948         }
6949         if(ifx)
6950           ifx->generated=1;
6951       }
6952       emit_skip++;
6953       offset++;
6954       if(res_offset < res_size-1)
6955         res_offset++;
6956     }
6957 /*       break; */
6958 /*     } */
6959   } else if(AOP_TYPE(right) == AOP_REG &&
6960             AOP_TYPE(left) != AOP_DIR){
6961
6962     while(size--) {
6963       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6964       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6965       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6966       if(rIfx.condition)
6967         emitSKPNZ;
6968       else
6969         emitSKPZ;
6970       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6971       offset++;
6972       if(res_offset < res_size-1)
6973         res_offset++;
6974     }
6975       
6976   }else{
6977     /* right is a pointer reg need both a & b */
6978     while(size--) {
6979       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6980       if(strcmp(l,"b"))
6981         pic16_emitcode("mov","b,%s",l);
6982       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6983       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6984       offset++;
6985     }
6986   }
6987
6988   if(result && preserve_result)
6989     {
6990       int i;
6991       for(i = 0; i < AOP_SIZE(result); i++)
6992         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6993     }
6994
6995   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6996
6997   if(result && preserve_result)
6998     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6999
7000   if(!rIfx.condition)
7001     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7002
7003   pic16_emitpLabel(lbl->key);
7004
7005   if(result && preserve_result)
7006     {
7007       int i;
7008       for(i = 0; i < AOP_SIZE(result); i++)
7009         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7010
7011       pic16_emitpLabel(lbl_done->key);
7012    }
7013
7014   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7015
7016   if(ifx)
7017     ifx->generated = 1;
7018 }
7019 #endif
7020
7021 #if 0
7022 /*-----------------------------------------------------------------*/
7023 /* gencjne - compare and jump if not equal                         */
7024 /*-----------------------------------------------------------------*/
7025 static void gencjne(operand *left, operand *right, iCode *ifx)
7026 {
7027     symbol *tlbl  = newiTempLabel(NULL);
7028
7029     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7030     gencjneshort(left, right, lbl);
7031
7032     pic16_emitcode("mov","a,%s",one);
7033     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7034     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7035     pic16_emitcode("clr","a");
7036     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7037
7038     pic16_emitpLabel(lbl->key);
7039     pic16_emitpLabel(tlbl->key);
7040
7041 }
7042 #endif
7043
7044
7045 /*-----------------------------------------------------------------*/
7046 /* is_LitOp - check if operand has to be treated as literal        */
7047 /*-----------------------------------------------------------------*/
7048 static bool is_LitOp(operand *op)
7049 {
7050   return ((AOP_TYPE(op) == AOP_LIT)
7051       || ( (AOP_TYPE(op) == AOP_PCODE)
7052           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7053               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7054 }
7055
7056 /*-----------------------------------------------------------------*/
7057 /* is_LitAOp - check if operand has to be treated as literal        */
7058 /*-----------------------------------------------------------------*/
7059 static bool is_LitAOp(asmop *aop)
7060 {
7061   return ((aop->type == AOP_LIT)
7062       || ( (aop->type == AOP_PCODE)
7063           && ( (aop->aopu.pcop->type == PO_LITERAL)
7064               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7065 }
7066
7067
7068
7069 /*-----------------------------------------------------------------*/
7070 /* genCmpEq - generates code for equal to                          */
7071 /*-----------------------------------------------------------------*/
7072 static void genCmpEq (iCode *ic, iCode *ifx)
7073 {
7074   operand *left, *right, *result;
7075   symbol *falselbl = newiTempLabel(NULL);
7076   symbol *donelbl = newiTempLabel(NULL);
7077
7078   int preserve_result = 0;
7079   int generate_result = 0;
7080   int i=0;
7081   unsigned long lit = -1;
7082
7083   FENTRY;
7084   
7085   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7086   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7087   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7088  
7089   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7090
7091   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7092     {
7093       werror(W_POSSBUG2, __FILE__, __LINE__);
7094       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7095       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7096       goto release;
7097     }
7098
7099   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7100     {
7101       operand *tmp = right ;
7102       right = left;
7103       left = tmp;
7104     }
7105
7106   if (AOP_TYPE(right) == AOP_LIT) {
7107     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7108   }
7109
7110   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7111     preserve_result = 1;
7112
7113   if(result && AOP_SIZE(result))
7114     generate_result = 1;
7115
7116   if(generate_result && !preserve_result)
7117     {
7118       for(i = 0; i < AOP_SIZE(result); i++)
7119         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7120     }
7121
7122   for(i=0; i < AOP_SIZE(left); i++)
7123     {
7124       if(AOP_TYPE(left) != AOP_ACC)
7125         {
7126           if(is_LitOp(left))
7127             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7128           else
7129             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7130         }
7131       if(is_LitOp(right)) {
7132         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7133           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7134         }
7135       } else
7136         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7137
7138       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7139     }
7140
7141   // result == true
7142
7143   if(generate_result && preserve_result)
7144     {
7145       for(i = 0; i < AOP_SIZE(result); i++)
7146         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7147     }
7148
7149   if(generate_result)
7150     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7151
7152   if(generate_result && preserve_result)
7153     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7154
7155   if(ifx && IC_TRUE(ifx))
7156     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7157
7158   if(ifx && IC_FALSE(ifx))
7159     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7160
7161   pic16_emitpLabel(falselbl->key);
7162
7163   // result == false
7164
7165   if(ifx && IC_FALSE(ifx))
7166     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7167
7168   if(generate_result && preserve_result)
7169     {
7170       for(i = 0; i < AOP_SIZE(result); i++)
7171         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7172     }
7173
7174   pic16_emitpLabel(donelbl->key);
7175
7176   if(ifx)
7177     ifx->generated = 1;
7178
7179 release:
7180   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7181   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7182   pic16_freeAsmop(result,NULL,ic,TRUE);
7183
7184 }
7185
7186
7187 #if 0
7188 // old version kept for reference
7189
7190 /*-----------------------------------------------------------------*/
7191 /* genCmpEq - generates code for equal to                          */
7192 /*-----------------------------------------------------------------*/
7193 static void genCmpEq (iCode *ic, iCode *ifx)
7194 {
7195     operand *left, *right, *result;
7196     unsigned long lit = 0L;
7197     int size,offset=0;
7198     symbol *falselbl  = newiTempLabel(NULL);
7199
7200
7201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7202
7203     if(ifx)
7204       DEBUGpic16_emitcode ("; ifx is non-null","");
7205     else
7206       DEBUGpic16_emitcode ("; ifx is null","");
7207
7208     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7209     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7210     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7211
7212     size = max(AOP_SIZE(left),AOP_SIZE(right));
7213
7214     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7215
7216     /* if literal, literal on the right or 
7217     if the right is in a pointer register and left 
7218     is not */
7219     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7220         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7221       operand *tmp = right ;
7222       right = left;
7223       left = tmp;
7224     }
7225
7226
7227     if(ifx && !AOP_SIZE(result)){
7228         symbol *tlbl;
7229         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7230         /* if they are both bit variables */
7231         if (AOP_TYPE(left) == AOP_CRY &&
7232             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7233                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7234             if(AOP_TYPE(right) == AOP_LIT){
7235                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7236                 if(lit == 0L){
7237                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7238                     pic16_emitcode("cpl","c");
7239                 } else if(lit == 1L) {
7240                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7241                 } else {
7242                     pic16_emitcode("clr","c");
7243                 }
7244                 /* AOP_TYPE(right) == AOP_CRY */
7245             } else {
7246                 symbol *lbl = newiTempLabel(NULL);
7247                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7248                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7249                 pic16_emitcode("cpl","c");
7250                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7251             }
7252             /* if true label then we jump if condition
7253             supplied is true */
7254             tlbl = newiTempLabel(NULL);
7255             if ( IC_TRUE(ifx) ) {
7256                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7257                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7258             } else {
7259                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7260                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7261             }
7262             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7263
7264                 {
7265                 /* left and right are both bit variables, result is carry */
7266                         resolvedIfx rIfx;
7267               
7268                         resolveIfx(&rIfx,ifx);
7269
7270                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7271                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7272                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7273                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7274                         genSkipz2(&rIfx,0);
7275                 }
7276         } else {
7277
7278                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7279
7280                         /* They're not both bit variables. Is the right a literal? */
7281                         if(AOP_TYPE(right) == AOP_LIT) {
7282                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7283             
7284                         switch(size) {
7285
7286                                 case 1:
7287                                         switch(lit & 0xff) {
7288                                                 case 1:
7289                                                                 if ( IC_TRUE(ifx) ) {
7290                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7291                                                                         emitSKPNZ;
7292                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7293                                                                 } else {
7294                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7295                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7296                                                                 }
7297                                                                 break;
7298                                                 case 0xff:
7299                                                                 if ( IC_TRUE(ifx) ) {
7300                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7301                                                                         emitSKPNZ;
7302                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7303                                                                 } else {
7304                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7305                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7306                                                                 }
7307                                                                 break;
7308                                                 default:
7309                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7310                                                                 if(lit)
7311                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7312                                                                 genSkip(ifx,'z');
7313                                         } // switch lit
7314
7315
7316                                         /* end of size == 1 */
7317                                         break;
7318               
7319                                 case 2:
7320                                         genc16bit2lit(left,lit,offset);
7321                                         genSkip(ifx,'z');
7322                                         break;
7323                                         /* end of size == 2 */
7324
7325                                 default:
7326                                         /* size is 4 */
7327                                         if(lit==0) {
7328                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7329                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7330                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7331                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7332                                                 genSkip(ifx,'z');
7333                                         } else {
7334                                                 /* search for patterns that can be optimized */
7335
7336                                                 genc16bit2lit(left,lit,0);
7337                                                 lit >>= 16;
7338                                                 if(lit) {
7339                                                                 if(IC_TRUE(ifx))
7340                                                                 emitSKPZ; // if hi word unequal
7341                                                                 else
7342                                                                 emitSKPNZ; // if hi word equal
7343                                                                 // fail early
7344                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7345                                                         genc16bit2lit(left,lit,2);
7346                                                         genSkip(ifx,'z');
7347                                                 } else {
7348                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7349                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7350                                                         genSkip(ifx,'z');
7351                                                 }
7352                                         }
7353                                                 pic16_emitpLabel(falselbl->key);
7354                                                 break;
7355
7356                         } // switch size
7357           
7358                         ifx->generated = 1;
7359                         goto release ;
7360             
7361
7362           } else if(AOP_TYPE(right) == AOP_CRY ) {
7363             /* we know the left is not a bit, but that the right is */
7364             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7365             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7366                       pic16_popGet(AOP(right),offset));
7367             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7368
7369             /* if the two are equal, then W will be 0 and the Z bit is set
7370              * we could test Z now, or go ahead and check the high order bytes if
7371              * the variable we're comparing is larger than a byte. */
7372
7373             while(--size)
7374               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7375
7376             if ( IC_TRUE(ifx) ) {
7377               emitSKPNZ;
7378               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7379               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7380             } else {
7381               emitSKPZ;
7382               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7383               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7384             }
7385
7386           } else {
7387             /* They're both variables that are larger than bits */
7388             int s = size;
7389
7390             tlbl = newiTempLabel(NULL);
7391
7392             while(size--) {
7393               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7394               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7395
7396               if ( IC_TRUE(ifx) ) {
7397                 if(size) {
7398                   emitSKPZ;
7399                 
7400                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7401
7402                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7403                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7404                 } else {
7405                   emitSKPNZ;
7406
7407                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7408
7409
7410                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7411                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7412                 }
7413               } else {
7414                 emitSKPZ;
7415
7416                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7417
7418                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7419                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7420               }
7421               offset++;
7422             }
7423             if(s>1 && IC_TRUE(ifx)) {
7424               pic16_emitpLabel(tlbl->key);
7425               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7426             }
7427           }
7428         }
7429         /* mark the icode as generated */
7430         ifx->generated = 1;
7431         goto release ;
7432     }
7433
7434     /* if they are both bit variables */
7435     if (AOP_TYPE(left) == AOP_CRY &&
7436         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7437         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7438         if(AOP_TYPE(right) == AOP_LIT){
7439             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7440             if(lit == 0L){
7441                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7442                 pic16_emitcode("cpl","c");
7443             } else if(lit == 1L) {
7444                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7445             } else {
7446                 pic16_emitcode("clr","c");
7447             }
7448             /* AOP_TYPE(right) == AOP_CRY */
7449         } else {
7450             symbol *lbl = newiTempLabel(NULL);
7451             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7452             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7453             pic16_emitcode("cpl","c");
7454             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7455         }
7456         /* c = 1 if egal */
7457         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7458             pic16_outBitC(result);
7459             goto release ;
7460         }
7461         if (ifx) {
7462             genIfxJump (ifx,"c");
7463             goto release ;
7464         }
7465         /* if the result is used in an arithmetic operation
7466         then put the result in place */
7467         pic16_outBitC(result);
7468     } else {
7469       
7470       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7471       gencjne(left,right,result,ifx);
7472 /*
7473       if(ifx) 
7474         gencjne(left,right,newiTempLabel(NULL));
7475       else {
7476         if(IC_TRUE(ifx)->key)
7477           gencjne(left,right,IC_TRUE(ifx)->key);
7478         else
7479           gencjne(left,right,IC_FALSE(ifx)->key);
7480         ifx->generated = 1;
7481         goto release ;
7482       }
7483       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7484         pic16_aopPut(AOP(result),"a",0);
7485         goto release ;
7486       }
7487
7488       if (ifx) {
7489         genIfxJump (ifx,"a");
7490         goto release ;
7491       }
7492 */
7493       /* if the result is used in an arithmetic operation
7494          then put the result in place */
7495 /*
7496       if (AOP_TYPE(result) != AOP_CRY) 
7497         pic16_outAcc(result);
7498 */
7499       /* leave the result in acc */
7500     }
7501
7502 release:
7503     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7504     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7505     pic16_freeAsmop(result,NULL,ic,TRUE);
7506 }
7507 #endif
7508
7509 /*-----------------------------------------------------------------*/
7510 /* ifxForOp - returns the icode containing the ifx for operand     */
7511 /*-----------------------------------------------------------------*/
7512 static iCode *ifxForOp ( operand *op, iCode *ic )
7513 {
7514   FENTRY2;
7515
7516     /* if true symbol then needs to be assigned */
7517     if (IS_TRUE_SYMOP(op))
7518         return NULL ;
7519
7520     /* if this has register type condition and
7521     the next instruction is ifx with the same operand
7522     and live to of the operand is upto the ifx only then */
7523     if (ic->next
7524         && ic->next->op == IFX
7525         && IC_COND(ic->next)->key == op->key
7526         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7527         ) {
7528                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7529           return ic->next;
7530     }
7531
7532     /*
7533     if (ic->next &&
7534         ic->next->op == IFX &&
7535         IC_COND(ic->next)->key == op->key) {
7536       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7537       return ic->next;
7538     }
7539     */
7540
7541     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7542     if (ic->next &&
7543         ic->next->op == IFX)
7544       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7545
7546     if (ic->next &&
7547         ic->next->op == IFX &&
7548         IC_COND(ic->next)->key == op->key) {
7549       DEBUGpic16_emitcode ("; "," key is okay");
7550       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7551                            OP_SYMBOL(op)->liveTo,
7552                            ic->next->seq);
7553     }
7554
7555 #if 0
7556     /* the code below is completely untested
7557      * it just allows ulong2fs.c compile -- VR */
7558          
7559     ic = ic->next;
7560     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7561                                         __FILE__, __FUNCTION__, __LINE__);
7562         
7563     /* if this has register type condition and
7564     the next instruction is ifx with the same operand
7565     and live to of the operand is upto the ifx only then */
7566     if (ic->next &&
7567         ic->next->op == IFX &&
7568         IC_COND(ic->next)->key == op->key &&
7569         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7570         return ic->next;
7571
7572     if (ic->next &&
7573         ic->next->op == IFX &&
7574         IC_COND(ic->next)->key == op->key) {
7575       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7576       return ic->next;
7577     }
7578
7579     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7580                                         __FILE__, __FUNCTION__, __LINE__);
7581
7582 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7583 #endif
7584
7585     return NULL;
7586 }
7587 /*-----------------------------------------------------------------*/
7588 /* genAndOp - for && operation                                     */
7589 /*-----------------------------------------------------------------*/
7590 static void genAndOp (iCode *ic)
7591 {
7592   operand *left,*right, *result;
7593 /*     symbol *tlbl; */
7594
7595     FENTRY;
7596
7597     /* note here that && operations that are in an
7598     if statement are taken away by backPatchLabels
7599     only those used in arthmetic operations remain */
7600     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7601     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7602     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7603
7604     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7605
7606     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7607     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7608     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7609
7610     /* if both are bit variables */
7611 /*     if (AOP_TYPE(left) == AOP_CRY && */
7612 /*         AOP_TYPE(right) == AOP_CRY ) { */
7613 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7614 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7615 /*         pic16_outBitC(result); */
7616 /*     } else { */
7617 /*         tlbl = newiTempLabel(NULL); */
7618 /*         pic16_toBoolean(left);     */
7619 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7620 /*         pic16_toBoolean(right); */
7621 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7622 /*         pic16_outBitAcc(result); */
7623 /*     } */
7624
7625     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7626     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7627     pic16_freeAsmop(result,NULL,ic,TRUE);
7628 }
7629
7630
7631 /*-----------------------------------------------------------------*/
7632 /* genOrOp - for || operation                                      */
7633 /*-----------------------------------------------------------------*/
7634 /*
7635   tsd pic port -
7636   modified this code, but it doesn't appear to ever get called
7637 */
7638
7639 static void genOrOp (iCode *ic)
7640 {
7641   operand *left,*right, *result;
7642   symbol *tlbl;
7643
7644     FENTRY;  
7645
7646   /* note here that || operations that are in an
7647     if statement are taken away by backPatchLabels
7648     only those used in arthmetic operations remain */
7649     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7650     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7651     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7652
7653     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7654
7655     /* if both are bit variables */
7656     if (AOP_TYPE(left) == AOP_CRY &&
7657         AOP_TYPE(right) == AOP_CRY ) {
7658       pic16_emitcode("clrc","");
7659       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7660                AOP(left)->aopu.aop_dir,
7661                AOP(left)->aopu.aop_dir);
7662       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7663                AOP(right)->aopu.aop_dir,
7664                AOP(right)->aopu.aop_dir);
7665       pic16_emitcode("setc","");
7666
7667     } else {
7668         tlbl = newiTempLabel(NULL);
7669         pic16_toBoolean(left);
7670         emitSKPZ;
7671         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7672         pic16_toBoolean(right);
7673         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7674
7675         pic16_outBitAcc(result);
7676     }
7677
7678     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680     pic16_freeAsmop(result,NULL,ic,TRUE);            
7681 }
7682
7683 /*-----------------------------------------------------------------*/
7684 /* isLiteralBit - test if lit == 2^n                               */
7685 /*-----------------------------------------------------------------*/
7686 static int isLiteralBit(unsigned long lit)
7687 {
7688     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7689     0x100L,0x200L,0x400L,0x800L,
7690     0x1000L,0x2000L,0x4000L,0x8000L,
7691     0x10000L,0x20000L,0x40000L,0x80000L,
7692     0x100000L,0x200000L,0x400000L,0x800000L,
7693     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7694     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7695     int idx;
7696     
7697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7698     for(idx = 0; idx < 32; idx++)
7699         if(lit == pw[idx])
7700             return idx+1;
7701     return 0;
7702 }
7703
7704 /*-----------------------------------------------------------------*/
7705 /* continueIfTrue -                                                */
7706 /*-----------------------------------------------------------------*/
7707 static void continueIfTrue (iCode *ic)
7708 {
7709   FENTRY;
7710   if(IC_TRUE(ic))
7711     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7712   ic->generated = 1;
7713 }
7714
7715 /*-----------------------------------------------------------------*/
7716 /* jmpIfTrue -                                                     */
7717 /*-----------------------------------------------------------------*/
7718 static void jumpIfTrue (iCode *ic)
7719 {
7720   FENTRY;
7721   if(!IC_TRUE(ic))
7722     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7723   ic->generated = 1;
7724 }
7725
7726 /*-----------------------------------------------------------------*/
7727 /* jmpTrueOrFalse -                                                */
7728 /*-----------------------------------------------------------------*/
7729 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7730 {
7731   // ugly but optimized by peephole
7732   FENTRY;
7733   if(IC_TRUE(ic)){
7734     symbol *nlbl = newiTempLabel(NULL);
7735       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7736       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7737       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7738       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7739   } else {
7740     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7741     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7742   }
7743   ic->generated = 1;
7744 }
7745
7746 /*-----------------------------------------------------------------*/
7747 /* genAnd  - code for and                                          */
7748 /*-----------------------------------------------------------------*/
7749 static void genAnd (iCode *ic, iCode *ifx)
7750 {
7751   operand *left, *right, *result;
7752   int size, offset=0;  
7753   unsigned long lit = 0L;
7754   int bytelit = 0;
7755   resolvedIfx rIfx;
7756
7757     FENTRY;
7758     
7759   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7760   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7761   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7762
7763   resolveIfx(&rIfx,ifx);
7764
7765   /* if left is a literal & right is not then exchange them */
7766   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7767       AOP_NEEDSACC(left)) {
7768     operand *tmp = right ;
7769     right = left;
7770     left = tmp;
7771   }
7772
7773   /* if result = right then exchange them */
7774   if(pic16_sameRegs(AOP(result),AOP(right))){
7775     operand *tmp = right ;
7776     right = left;
7777     left = tmp;
7778   }
7779
7780   /* if right is bit then exchange them */
7781   if (AOP_TYPE(right) == AOP_CRY &&
7782       AOP_TYPE(left) != AOP_CRY){
7783     operand *tmp = right ;
7784     right = left;
7785     left = tmp;
7786   }
7787   if(AOP_TYPE(right) == AOP_LIT)
7788     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7789
7790   size = AOP_SIZE(result);
7791
7792   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7793
7794   // if(bit & yy)
7795   // result = bit & yy;
7796   if (AOP_TYPE(left) == AOP_CRY){
7797     // c = bit & literal;
7798     if(AOP_TYPE(right) == AOP_LIT){
7799       if(lit & 1) {
7800         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7801           // no change
7802           goto release;
7803         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7804       } else {
7805         // bit(result) = 0;
7806         if(size && (AOP_TYPE(result) == AOP_CRY)){
7807           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7808           goto release;
7809         }
7810         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7811           jumpIfTrue(ifx);
7812           goto release;
7813         }
7814         pic16_emitcode("clr","c");
7815       }
7816     } else {
7817       if (AOP_TYPE(right) == AOP_CRY){
7818         // c = bit & bit;
7819         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7820         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7821       } else {
7822         // c = bit & val;
7823         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7824         // c = lsb
7825         pic16_emitcode("rrc","a");
7826         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7827       }
7828     }
7829     // bit = c
7830     // val = c
7831     if(size)
7832       pic16_outBitC(result);
7833     // if(bit & ...)
7834     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7835       genIfxJump(ifx, "c");           
7836     goto release ;
7837   }
7838
7839   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7840   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7841   if((AOP_TYPE(right) == AOP_LIT) &&
7842      (AOP_TYPE(result) == AOP_CRY) &&
7843      (AOP_TYPE(left) != AOP_CRY)){
7844     int posbit = isLiteralBit(lit);
7845     /* left &  2^n */
7846     if(posbit){
7847       posbit--;
7848       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7849       // bit = left & 2^n
7850       if(size)
7851         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7852       // if(left &  2^n)
7853       else{
7854         if(ifx){
7855 /*
7856           if(IC_TRUE(ifx)) {
7857             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7858             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7859           } else {
7860             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7861             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7862           }
7863 */
7864         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7865         size = AOP_SIZE(left);
7866
7867         {
7868           int bp = posbit, ofs=0;
7869           
7870             while(bp > 7) {
7871               bp -= 8;
7872               ofs++;
7873             }
7874         
7875           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7876                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7877
7878         }
7879 /*
7880           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7881                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7882 */
7883           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7884           
7885           ifx->generated = 1;
7886         }
7887         goto release;
7888       }
7889     } else {
7890       symbol *tlbl = newiTempLabel(NULL);
7891       int sizel = AOP_SIZE(left);
7892
7893       if(size)
7894         emitSETC;
7895
7896       while(sizel--) {
7897         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7898
7899           /* patch provided by Aaron Colwell */
7900           if((posbit = isLiteralBit(bytelit)) != 0) {
7901               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7902                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7903                                                 (posbit-1),0, PO_GPR_REGISTER));
7904
7905               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7906 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7907           } else {
7908               if (bytelit == 0xff) {
7909                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7910                    * a peephole could optimize it out -- VR */
7911                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7912               } else {
7913                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7914                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7915               }
7916
7917               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7918                             pic16_popGetLabel(tlbl->key));
7919           }
7920         
7921 #if 0
7922           /* old code, left here for reference -- VR 09/2004 */
7923           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924           // byte ==  2^n ?
7925           if((posbit = isLiteralBit(bytelit)) != 0)
7926             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7927           else{
7928             if(bytelit != 0x0FFL)
7929               pic16_emitcode("anl","a,%s",
7930                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7931             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7932           }
7933 #endif
7934         }
7935         offset++;
7936       }
7937       // bit = left & literal
7938       if(size) {
7939         emitCLRC;
7940         pic16_emitpLabel(tlbl->key);
7941       }
7942       // if(left & literal)
7943       else {
7944         if(ifx) {
7945           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7946           ifx->generated = 1;
7947         }
7948         pic16_emitpLabel(tlbl->key);
7949         goto release;
7950       }
7951     }
7952
7953     pic16_outBitC(result);
7954     goto release ;
7955   }
7956
7957   /* if left is same as result */
7958   if(pic16_sameRegs(AOP(result),AOP(left))){
7959     int know_W = -1;
7960     for(;size--; offset++,lit>>=8) {
7961       if(AOP_TYPE(right) == AOP_LIT){
7962         switch(lit & 0xff) {
7963         case 0x00:
7964           /*  and'ing with 0 has clears the result */
7965 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7966           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7967           break;
7968         case 0xff:
7969           /* and'ing with 0xff is a nop when the result and left are the same */
7970           break;
7971
7972         default:
7973           {
7974             int p = pic16_my_powof2( (~lit) & 0xff );
7975             if(p>=0) {
7976               /* only one bit is set in the literal, so use a bcf instruction */
7977 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7978               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7979
7980             } else {
7981               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7982               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7983               if(know_W != (lit&0xff))
7984                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7985               know_W = lit &0xff;
7986               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7987             }
7988           }    
7989         }
7990       } else {
7991         if (AOP_TYPE(left) == AOP_ACC) {
7992           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7993         } else {                    
7994           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7995           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7996
7997         }
7998       }
7999     }
8000
8001   } else {
8002     // left & result in different registers
8003     if(AOP_TYPE(result) == AOP_CRY){
8004       // result = bit
8005       // if(size), result in bit
8006       // if(!size && ifx), conditional oper: if(left & right)
8007       symbol *tlbl = newiTempLabel(NULL);
8008       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8009       if(size)
8010         pic16_emitcode("setb","c");
8011       while(sizer--){
8012         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8013         pic16_emitcode("anl","a,%s",
8014                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8015         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8016         offset++;
8017       }
8018       if(size){
8019         CLRC;
8020         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8021         pic16_outBitC(result);
8022       } else if(ifx)
8023         jmpTrueOrFalse(ifx, tlbl);
8024     } else {
8025       for(;(size--);offset++) {
8026         // normal case
8027         // result = left & right
8028         if(AOP_TYPE(right) == AOP_LIT){
8029           int t = (lit >> (offset*8)) & 0x0FFL;
8030           switch(t) { 
8031           case 0x00:
8032             pic16_emitcode("clrf","%s",
8033                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8034             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8035             break;
8036           case 0xff:
8037             pic16_emitcode("movf","%s,w",
8038                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8039             pic16_emitcode("movwf","%s",
8040                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8041             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8042             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8043             break;
8044           default:
8045             pic16_emitcode("movlw","0x%x",t);
8046             pic16_emitcode("andwf","%s,w",
8047                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8048             pic16_emitcode("movwf","%s",
8049                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8050               
8051             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8052             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8053             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8054           }
8055           continue;
8056         }
8057
8058         if (AOP_TYPE(left) == AOP_ACC) {
8059           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8060           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8061         } else {
8062           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8063           pic16_emitcode("andwf","%s,w",
8064                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8065           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8066           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8067         }
8068         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8069         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8070       }
8071     }
8072   }
8073
8074   release :
8075     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8076   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8077   pic16_freeAsmop(result,NULL,ic,TRUE);     
8078 }
8079
8080 /*-----------------------------------------------------------------*/
8081 /* genOr  - code for or                                            */
8082 /*-----------------------------------------------------------------*/
8083 static void genOr (iCode *ic, iCode *ifx)
8084 {
8085     operand *left, *right, *result;
8086     int size, offset=0;
8087     unsigned long lit = 0L;
8088
8089     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8090
8091     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8092     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8093     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8094
8095     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8096
8097     /* if left is a literal & right is not then exchange them */
8098     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8099         AOP_NEEDSACC(left)) {
8100         operand *tmp = right ;
8101         right = left;
8102         left = tmp;
8103     }
8104
8105     /* if result = right then exchange them */
8106     if(pic16_sameRegs(AOP(result),AOP(right))){
8107         operand *tmp = right ;
8108         right = left;
8109         left = tmp;
8110     }
8111
8112     /* if right is bit then exchange them */
8113     if (AOP_TYPE(right) == AOP_CRY &&
8114         AOP_TYPE(left) != AOP_CRY){
8115         operand *tmp = right ;
8116         right = left;
8117         left = tmp;
8118     }
8119
8120     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8121
8122     if(AOP_TYPE(right) == AOP_LIT)
8123         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8124
8125     size = AOP_SIZE(result);
8126
8127     // if(bit | yy)
8128     // xx = bit | yy;
8129     if (AOP_TYPE(left) == AOP_CRY){
8130         if(AOP_TYPE(right) == AOP_LIT){
8131             // c = bit & literal;
8132             if(lit){
8133                 // lit != 0 => result = 1
8134                 if(AOP_TYPE(result) == AOP_CRY){
8135                   if(size)
8136                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8137                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8138                   //     AOP(result)->aopu.aop_dir,
8139                   //     AOP(result)->aopu.aop_dir);
8140                     else if(ifx)
8141                         continueIfTrue(ifx);
8142                     goto release;
8143                 }
8144             } else {
8145                 // lit == 0 => result = left
8146                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8147                     goto release;
8148                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8149             }
8150         } else {
8151             if (AOP_TYPE(right) == AOP_CRY){
8152               if(pic16_sameRegs(AOP(result),AOP(left))){
8153                 // c = bit | bit;
8154                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8155                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8156                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8157
8158                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8159                          AOP(result)->aopu.aop_dir,
8160                          AOP(result)->aopu.aop_dir);
8161                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8162                          AOP(right)->aopu.aop_dir,
8163                          AOP(right)->aopu.aop_dir);
8164                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8165                          AOP(result)->aopu.aop_dir,
8166                          AOP(result)->aopu.aop_dir);
8167               } else {
8168                 if( AOP_TYPE(result) == AOP_ACC) {
8169                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8170                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8171                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8172                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8173
8174                 } else {
8175
8176                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8177                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8178                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8179                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8180
8181                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8182                                  AOP(result)->aopu.aop_dir,
8183                                  AOP(result)->aopu.aop_dir);
8184                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8185                                  AOP(right)->aopu.aop_dir,
8186                                  AOP(right)->aopu.aop_dir);
8187                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8188                                  AOP(left)->aopu.aop_dir,
8189                                  AOP(left)->aopu.aop_dir);
8190                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8191                                  AOP(result)->aopu.aop_dir,
8192                                  AOP(result)->aopu.aop_dir);
8193                 }
8194               }
8195             } else {
8196                 // c = bit | val;
8197                 symbol *tlbl = newiTempLabel(NULL);
8198                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8199
8200
8201                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8202                 if( AOP_TYPE(right) == AOP_ACC) {
8203                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8204                   emitSKPNZ;
8205                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8206                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8207                 }
8208
8209
8210
8211                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8212                     pic16_emitcode(";XXX setb","c");
8213                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8214                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8215                 pic16_toBoolean(right);
8216                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8217                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8218                     jmpTrueOrFalse(ifx, tlbl);
8219                     goto release;
8220                 } else {
8221                     CLRC;
8222                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8223                 }
8224             }
8225         }
8226         // bit = c
8227         // val = c
8228         if(size)
8229             pic16_outBitC(result);
8230         // if(bit | ...)
8231         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8232             genIfxJump(ifx, "c");           
8233         goto release ;
8234     }
8235
8236     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8237     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8238     if((AOP_TYPE(right) == AOP_LIT) &&
8239        (AOP_TYPE(result) == AOP_CRY) &&
8240        (AOP_TYPE(left) != AOP_CRY)){
8241         if(lit){
8242           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8243             // result = 1
8244             if(size)
8245                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8246             else 
8247                 continueIfTrue(ifx);
8248             goto release;
8249         } else {
8250           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8251             // lit = 0, result = boolean(left)
8252             if(size)
8253                 pic16_emitcode(";XXX setb","c");
8254             pic16_toBoolean(right);
8255             if(size){
8256                 symbol *tlbl = newiTempLabel(NULL);
8257                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8258                 CLRC;
8259                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8260             } else {
8261                 genIfxJump (ifx,"a");
8262                 goto release;
8263             }
8264         }
8265         pic16_outBitC(result);
8266         goto release ;
8267     }
8268
8269     /* if left is same as result */
8270     if(pic16_sameRegs(AOP(result),AOP(left))){
8271       int know_W = -1;
8272       for(;size--; offset++,lit>>=8) {
8273         if(AOP_TYPE(right) == AOP_LIT){
8274           if((lit & 0xff) == 0)
8275             /*  or'ing with 0 has no effect */
8276             continue;
8277           else {
8278             int p = pic16_my_powof2(lit & 0xff);
8279             if(p>=0) {
8280               /* only one bit is set in the literal, so use a bsf instruction */
8281               pic16_emitpcode(POC_BSF,
8282                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8283             } else {
8284               if(know_W != (lit & 0xff))
8285                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8286               know_W = lit & 0xff;
8287               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8288             }
8289                     
8290           }
8291         } else {
8292           if (AOP_TYPE(left) == AOP_ACC) {
8293             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8294             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8295           } else {                  
8296             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8297             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8298
8299             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8300             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8301
8302           }
8303         }
8304       }
8305     } else {
8306         // left & result in different registers
8307         if(AOP_TYPE(result) == AOP_CRY){
8308             // result = bit
8309             // if(size), result in bit
8310             // if(!size && ifx), conditional oper: if(left | right)
8311             symbol *tlbl = newiTempLabel(NULL);
8312             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8313             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8314
8315
8316             if(size)
8317                 pic16_emitcode(";XXX setb","c");
8318             while(sizer--){
8319                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8320                 pic16_emitcode(";XXX orl","a,%s",
8321                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8322                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8323                 offset++;
8324             }
8325             if(size){
8326                 CLRC;
8327                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8328                 pic16_outBitC(result);
8329             } else if(ifx)
8330                 jmpTrueOrFalse(ifx, tlbl);
8331         } else for(;(size--);offset++){
8332           // normal case
8333           // result = left & right
8334           if(AOP_TYPE(right) == AOP_LIT){
8335             int t = (lit >> (offset*8)) & 0x0FFL;
8336             switch(t) { 
8337             case 0x00:
8338               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8339               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8340
8341               pic16_emitcode("movf","%s,w",
8342                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8343               pic16_emitcode("movwf","%s",
8344                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8345               break;
8346             default:
8347               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8348               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8349               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8350
8351               pic16_emitcode("movlw","0x%x",t);
8352               pic16_emitcode("iorwf","%s,w",
8353                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8354               pic16_emitcode("movwf","%s",
8355                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8356               
8357             }
8358             continue;
8359           }
8360
8361           // faster than result <- left, anl result,right
8362           // and better if result is SFR
8363           if (AOP_TYPE(left) == AOP_ACC) {
8364             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8365             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8366           } else {
8367             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8368             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8369
8370             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371             pic16_emitcode("iorwf","%s,w",
8372                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8373           }
8374           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8375           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8376         }
8377     }
8378
8379 release :
8380     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8381     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8382     pic16_freeAsmop(result,NULL,ic,TRUE);     
8383 }
8384
8385 /*-----------------------------------------------------------------*/
8386 /* genXor - code for xclusive or                                   */
8387 /*-----------------------------------------------------------------*/
8388 static void genXor (iCode *ic, iCode *ifx)
8389 {
8390   operand *left, *right, *result;
8391   int size, offset=0;
8392   unsigned long lit = 0L;
8393
8394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8395
8396   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8397   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8398   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8399
8400   /* if left is a literal & right is not ||
8401      if left needs acc & right does not */
8402   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8403       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8404     operand *tmp = right ;
8405     right = left;
8406     left = tmp;
8407   }
8408
8409   /* if result = right then exchange them */
8410   if(pic16_sameRegs(AOP(result),AOP(right))){
8411     operand *tmp = right ;
8412     right = left;
8413     left = tmp;
8414   }
8415
8416   /* if right is bit then exchange them */
8417   if (AOP_TYPE(right) == AOP_CRY &&
8418       AOP_TYPE(left) != AOP_CRY){
8419     operand *tmp = right ;
8420     right = left;
8421     left = tmp;
8422   }
8423   if(AOP_TYPE(right) == AOP_LIT)
8424     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8425
8426   size = AOP_SIZE(result);
8427
8428   // if(bit ^ yy)
8429   // xx = bit ^ yy;
8430   if (AOP_TYPE(left) == AOP_CRY){
8431     if(AOP_TYPE(right) == AOP_LIT){
8432       // c = bit & literal;
8433       if(lit>>1){
8434         // lit>>1  != 0 => result = 1
8435         if(AOP_TYPE(result) == AOP_CRY){
8436           if(size)
8437             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8438             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8439           else if(ifx)
8440             continueIfTrue(ifx);
8441           goto release;
8442         }
8443         pic16_emitcode("setb","c");
8444       } else{
8445         // lit == (0 or 1)
8446         if(lit == 0){
8447           // lit == 0, result = left
8448           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8449             goto release;
8450           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8451         } else{
8452           // lit == 1, result = not(left)
8453           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8454             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8455             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8456             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8457             goto release;
8458           } else {
8459             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8460             pic16_emitcode("cpl","c");
8461           }
8462         }
8463       }
8464
8465     } else {
8466       // right != literal
8467       symbol *tlbl = newiTempLabel(NULL);
8468       if (AOP_TYPE(right) == AOP_CRY){
8469         // c = bit ^ bit;
8470         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8471       }
8472       else{
8473         int sizer = AOP_SIZE(right);
8474         // c = bit ^ val
8475         // if val>>1 != 0, result = 1
8476         pic16_emitcode("setb","c");
8477         while(sizer){
8478           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8479           if(sizer == 1)
8480             // test the msb of the lsb
8481             pic16_emitcode("anl","a,#0xfe");
8482           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8483           sizer--;
8484         }
8485         // val = (0,1)
8486         pic16_emitcode("rrc","a");
8487       }
8488       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8489       pic16_emitcode("cpl","c");
8490       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8491     }
8492     // bit = c
8493     // val = c
8494     if(size)
8495       pic16_outBitC(result);
8496     // if(bit | ...)
8497     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8498       genIfxJump(ifx, "c");           
8499     goto release ;
8500   }
8501
8502   if(pic16_sameRegs(AOP(result),AOP(left))){
8503     /* if left is same as result */
8504     for(;size--; offset++) {
8505       if(AOP_TYPE(right) == AOP_LIT){
8506         int t  = (lit >> (offset*8)) & 0x0FFL;
8507         if(t == 0x00L)
8508           continue;
8509         else
8510           if (IS_AOP_PREG(left)) {
8511             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8512             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8513             pic16_aopPut(AOP(result),"a",offset);
8514           } else {
8515             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8516             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8517             pic16_emitcode("xrl","%s,%s",
8518                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8519                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8520           }
8521       } else {
8522         if (AOP_TYPE(left) == AOP_ACC)
8523           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8524         else {
8525           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8526           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8527 /*
8528           if (IS_AOP_PREG(left)) {
8529             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8530             pic16_aopPut(AOP(result),"a",offset);
8531           } else
8532             pic16_emitcode("xrl","%s,a",
8533                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8534 */
8535         }
8536       }
8537     }
8538   } else {
8539     // left & result in different registers
8540     if(AOP_TYPE(result) == AOP_CRY){
8541       // result = bit
8542       // if(size), result in bit
8543       // if(!size && ifx), conditional oper: if(left ^ right)
8544       symbol *tlbl = newiTempLabel(NULL);
8545       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8546       if(size)
8547         pic16_emitcode("setb","c");
8548       while(sizer--){
8549         if((AOP_TYPE(right) == AOP_LIT) &&
8550            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8551           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8552         } else {
8553           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8554           pic16_emitcode("xrl","a,%s",
8555                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8556         }
8557         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8558         offset++;
8559       }
8560       if(size){
8561         CLRC;
8562         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8563         pic16_outBitC(result);
8564       } else if(ifx)
8565         jmpTrueOrFalse(ifx, tlbl);
8566     } else for(;(size--);offset++){
8567       // normal case
8568       // result = left & right
8569       if(AOP_TYPE(right) == AOP_LIT){
8570         int t = (lit >> (offset*8)) & 0x0FFL;
8571         switch(t) { 
8572         case 0x00:
8573           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8574           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8575           pic16_emitcode("movf","%s,w",
8576                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8577           pic16_emitcode("movwf","%s",
8578                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8579           break;
8580         case 0xff:
8581           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8582           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8583           pic16_emitcode("comf","%s,w",
8584                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8585           pic16_emitcode("movwf","%s",
8586                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8587           break;
8588         default:
8589           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8590           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8591           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8592           pic16_emitcode("movlw","0x%x",t);
8593           pic16_emitcode("xorwf","%s,w",
8594                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8595           pic16_emitcode("movwf","%s",
8596                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8597
8598         }
8599         continue;
8600       }
8601
8602       // faster than result <- left, anl result,right
8603       // and better if result is SFR
8604       if (AOP_TYPE(left) == AOP_ACC) {
8605         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8606         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8607       } else {
8608         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8609         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8610         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8611         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8612       }
8613       if ( AOP_TYPE(result) != AOP_ACC){
8614         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8615         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8616       }
8617     }
8618   }
8619
8620   release :
8621     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8622   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8623   pic16_freeAsmop(result,NULL,ic,TRUE);     
8624 }
8625
8626 /*-----------------------------------------------------------------*/
8627 /* genInline - write the inline code out                           */
8628 /*-----------------------------------------------------------------*/
8629 static void genInline (iCode *ic)
8630 {
8631   char *buffer, *bp, *bp1;
8632     
8633         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8634
8635         _G.inLine += (!options.asmpeep);
8636
8637         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8638         strcpy(buffer,IC_INLINE(ic));
8639
8640         while((bp1=strstr(bp, "\\n"))) {
8641           *bp1++ = '\n';
8642           *bp1++ = ' ';
8643           bp = bp1;
8644         }
8645         bp = bp1 = buffer;
8646         
8647         /* emit each line as a code */
8648         while (*bp) {
8649                 if (*bp == '\n') {
8650                         *bp++ = '\0';
8651
8652                         if(*bp1)
8653                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8654                         bp1 = bp;
8655                 } else {
8656                         if (*bp == ':') {
8657                                 bp++;
8658                                 *bp = '\0';
8659                                 bp++;
8660
8661                                 /* print label, use this special format with NULL directive
8662                                  * to denote that the argument should not be indented with tab */
8663                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8664                                 bp1 = bp;
8665                         } else
8666                                 bp++;
8667                 }
8668         }
8669
8670         if ((bp1 != bp) && *bp1)
8671                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8672
8673
8674     Safe_free(buffer);
8675
8676     _G.inLine -= (!options.asmpeep);
8677 }
8678
8679 /*-----------------------------------------------------------------*/
8680 /* genRRC - rotate right with carry                                */
8681 /*-----------------------------------------------------------------*/
8682 static void genRRC (iCode *ic)
8683 {
8684   operand *left , *result ;
8685   int size, offset = 0, same;
8686
8687   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8688
8689   /* rotate right with carry */
8690   left = IC_LEFT(ic);
8691   result=IC_RESULT(ic);
8692   pic16_aopOp (left,ic,FALSE);
8693   pic16_aopOp (result,ic,TRUE);
8694
8695   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8696
8697   same = pic16_sameRegs(AOP(result),AOP(left));
8698
8699   size = AOP_SIZE(result);    
8700
8701   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8702
8703   /* get the lsb and put it into the carry */
8704   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8705
8706   offset = 0 ;
8707
8708   while(size--) {
8709
8710     if(same) {
8711       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8712     } else {
8713       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8714       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8715     }
8716
8717     offset++;
8718   }
8719
8720   pic16_freeAsmop(left,NULL,ic,TRUE);
8721   pic16_freeAsmop(result,NULL,ic,TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genRLC - generate code for rotate left with carry               */
8726 /*-----------------------------------------------------------------*/
8727 static void genRLC (iCode *ic)
8728 {    
8729   operand *left , *result ;
8730   int size, offset = 0;
8731   int same;
8732
8733   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8734   /* rotate right with carry */
8735   left = IC_LEFT(ic);
8736   result=IC_RESULT(ic);
8737   pic16_aopOp (left,ic,FALSE);
8738   pic16_aopOp (result,ic,TRUE);
8739
8740   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8741
8742   same = pic16_sameRegs(AOP(result),AOP(left));
8743
8744   /* move it to the result */
8745   size = AOP_SIZE(result);    
8746
8747   /* get the msb and put it into the carry */
8748   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8749
8750   offset = 0 ;
8751
8752   while(size--) {
8753
8754     if(same) {
8755       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8756     } else {
8757       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8758       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8759     }
8760
8761     offset++;
8762   }
8763
8764
8765   pic16_freeAsmop(left,NULL,ic,TRUE);
8766   pic16_freeAsmop(result,NULL,ic,TRUE);
8767 }
8768
8769
8770 /* gpasm can get the highest order bit with HIGH/UPPER
8771  * so the following probably is not needed -- VR */
8772  
8773 /*-----------------------------------------------------------------*/
8774 /* genGetHbit - generates code get highest order bit               */
8775 /*-----------------------------------------------------------------*/
8776 static void genGetHbit (iCode *ic)
8777 {
8778     operand *left, *result;
8779     left = IC_LEFT(ic);
8780     result=IC_RESULT(ic);
8781     pic16_aopOp (left,ic,FALSE);
8782     pic16_aopOp (result,ic,FALSE);
8783
8784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8785     /* get the highest order byte into a */
8786     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8787     if(AOP_TYPE(result) == AOP_CRY){
8788         pic16_emitcode("rlc","a");
8789         pic16_outBitC(result);
8790     }
8791     else{
8792         pic16_emitcode("rl","a");
8793         pic16_emitcode("anl","a,#0x01");
8794         pic16_outAcc(result);
8795     }
8796
8797
8798     pic16_freeAsmop(left,NULL,ic,TRUE);
8799     pic16_freeAsmop(result,NULL,ic,TRUE);
8800 }
8801
8802 #if 0
8803 /*-----------------------------------------------------------------*/
8804 /* AccRol - rotate left accumulator by known count                 */
8805 /*-----------------------------------------------------------------*/
8806 static void AccRol (int shCount)
8807 {
8808     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809     shCount &= 0x0007;              // shCount : 0..7
8810     switch(shCount){
8811         case 0 :
8812             break;
8813         case 1 :
8814             pic16_emitcode("rl","a");
8815             break;
8816         case 2 :
8817             pic16_emitcode("rl","a");
8818             pic16_emitcode("rl","a");
8819             break;
8820         case 3 :
8821             pic16_emitcode("swap","a");
8822             pic16_emitcode("rr","a");
8823             break;
8824         case 4 :
8825             pic16_emitcode("swap","a");
8826             break;
8827         case 5 :
8828             pic16_emitcode("swap","a");
8829             pic16_emitcode("rl","a");
8830             break;
8831         case 6 :
8832             pic16_emitcode("rr","a");
8833             pic16_emitcode("rr","a");
8834             break;
8835         case 7 :
8836             pic16_emitcode("rr","a");
8837             break;
8838     }
8839 }
8840 #endif
8841
8842 /*-----------------------------------------------------------------*/
8843 /* AccLsh - left shift accumulator by known count                  */
8844 /*-----------------------------------------------------------------*/
8845 static void AccLsh (int shCount)
8846 {
8847         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8848         switch(shCount){
8849                 case 0 :
8850                         return;
8851                         break;
8852                 case 1 :
8853                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8854                         break;
8855                 case 2 :
8856                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8857                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8858                         break;
8859                 case 3 :
8860                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8861                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8862                         break;
8863                 case 4 :
8864                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8865                         break;
8866                 case 5 :
8867                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8868                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8869                         break;
8870                 case 6 :
8871                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8872                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8873                         break;
8874                 case 7 :
8875                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8876                         break;
8877         }
8878
8879         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8880 }
8881
8882 /*-----------------------------------------------------------------*/
8883 /* AccRsh - right shift accumulator by known count                 */
8884 /*-----------------------------------------------------------------*/
8885 static void AccRsh (int shCount, int andmask)
8886 {
8887         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888         switch(shCount){
8889                 case 0 :
8890                         return; break;
8891                 case 1 :
8892                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8893                         break;
8894                 case 2 :
8895                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8896                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8897                         break;
8898                 case 3 :
8899                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8900                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8901                         break;
8902                 case 4 :
8903                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8904                         break;
8905                 case 5 :
8906                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8907                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8908                         break;
8909                 case 6 :
8910                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8911                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8912                         break;
8913                 case 7 :
8914                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8915                         break;
8916         }
8917         
8918         if(andmask)
8919                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8920         else
8921                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8922 }
8923
8924 #if 0
8925 /*-----------------------------------------------------------------*/
8926 /* AccSRsh - signed right shift accumulator by known count                 */
8927 /*-----------------------------------------------------------------*/
8928 static void AccSRsh (int shCount)
8929 {
8930     symbol *tlbl ;
8931     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8932     if(shCount != 0){
8933         if(shCount == 1){
8934             pic16_emitcode("mov","c,acc.7");
8935             pic16_emitcode("rrc","a");
8936         } else if(shCount == 2){
8937             pic16_emitcode("mov","c,acc.7");
8938             pic16_emitcode("rrc","a");
8939             pic16_emitcode("mov","c,acc.7");
8940             pic16_emitcode("rrc","a");
8941         } else {
8942             tlbl = newiTempLabel(NULL);
8943             /* rotate right accumulator */
8944             AccRol(8 - shCount);
8945             /* and kill the higher order bits */
8946             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8947             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8948             pic16_emitcode("orl","a,#0x%02x",
8949                      (unsigned char)~SRMask[shCount]);
8950             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8951         }
8952     }
8953 }
8954 #endif
8955
8956 /*-----------------------------------------------------------------*/
8957 /* shiftR1Left2Result - shift right one byte from left to result   */
8958 /*-----------------------------------------------------------------*/
8959 static void shiftR1Left2ResultSigned (operand *left, int offl,
8960                                 operand *result, int offr,
8961                                 int shCount)
8962 {
8963   int same;
8964
8965   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8966
8967   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8968
8969   switch(shCount) {
8970   case 1:
8971     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8972     if(same) 
8973       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8974     else {
8975       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8976       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8977     }
8978
8979     break;
8980   case 2:
8981
8982     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8983     if(same) 
8984       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8985     else {
8986       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8987       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988     }
8989     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8990     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8991
8992     break;
8993
8994   case 3:
8995     if(same)
8996       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8997     else {
8998       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8999       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000     }
9001
9002     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9003     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9004     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9005
9006     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9007     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9008
9009     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9010     break;
9011
9012   case 4:
9013     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9014     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
9015     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9016     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
9017     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9018     break;
9019   case 5:
9020     if(same) {
9021       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
9022     } else {
9023       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
9024       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9025     }
9026     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
9027     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
9028     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9029     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
9030     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9031     break;
9032
9033   case 6:
9034     if(same) {
9035       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9036       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9037       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9038       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9039       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9040       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041     } else {
9042       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9043       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9044       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9046       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9047     }
9048     break;
9049
9050   case 7:
9051     if(same) {
9052       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9053       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9054       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9055       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9056     } else {
9057       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9058       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9059       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9060     }
9061
9062   default:
9063     break;
9064   }
9065 }
9066
9067 /*-----------------------------------------------------------------*/
9068 /* shiftR1Left2Result - shift right one byte from left to result   */
9069 /*-----------------------------------------------------------------*/
9070 static void shiftR1Left2Result (operand *left, int offl,
9071                                 operand *result, int offr,
9072                                 int shCount, int sign)
9073 {
9074   int same;
9075
9076   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9077
9078   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9079
9080   /* Copy the msb into the carry if signed. */
9081   if(sign) {
9082     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9083     return;
9084   }
9085
9086
9087
9088   switch(shCount) {
9089   case 1:
9090     emitCLRC;
9091     if(same) 
9092       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9093     else {
9094       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9095       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9096     }
9097     break;
9098   case 2:
9099     emitCLRC;
9100     if(same) {
9101       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9102     } else {
9103       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9104       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9105     }
9106     emitCLRC;
9107     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9108
9109     break;
9110   case 3:
9111     if(same)
9112       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9113     else {
9114       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9115       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9116     }
9117
9118     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9119     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9120     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9121     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9122     break;
9123       
9124   case 4:
9125     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9126     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9127     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9128     break;
9129
9130   case 5:
9131     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9132     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9133     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9134     //emitCLRC;
9135     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9136
9137     break;
9138   case 6:
9139
9140     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9141     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9142     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9143     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9144     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9145     break;
9146
9147   case 7:
9148
9149     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9150     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9151     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9152
9153     break;
9154
9155   default:
9156     break;
9157   }
9158 }
9159
9160 /*-----------------------------------------------------------------*/
9161 /* shiftL1Left2Result - shift left one byte from left to result    */
9162 /*-----------------------------------------------------------------*/
9163 static void shiftL1Left2Result (operand *left, int offl,
9164                                 operand *result, int offr, int shCount)
9165 {
9166   int same;
9167
9168   //    char *l;
9169   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9170
9171   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9172   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9173     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9174     //    MOVA(l);
9175     /* shift left accumulator */
9176     //AccLsh(shCount); // don't comment out just yet...
9177   //    pic16_aopPut(AOP(result),"a",offr);
9178
9179   switch(shCount) {
9180   case 1:
9181     /* Shift left 1 bit position */
9182     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9183     if(same) {
9184       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9185     } else {
9186       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9187       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9188     }
9189     break;
9190   case 2:
9191     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9192     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9193     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9194     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9195     break;
9196   case 3:
9197     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9198     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9199     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9200     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9201     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9202     break;
9203   case 4:
9204     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9205     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9206     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9207     break;
9208   case 5:
9209     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9210     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9211     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9212     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9213     break;
9214   case 6:
9215     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9216     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9217     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9218     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9219     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9220     break;
9221   case 7:
9222     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9223     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9224     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9225     break;
9226
9227   default:
9228     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9229   }
9230
9231 }
9232
9233 /*-----------------------------------------------------------------*/
9234 /* movLeft2Result - move byte from left to result                  */
9235 /*-----------------------------------------------------------------*/
9236 static void movLeft2Result (operand *left, int offl,
9237                             operand *result, int offr)
9238 {
9239   char *l;
9240   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9241   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9242     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9243
9244     if (*l == '@' && (IS_AOP_PREG(result))) {
9245       pic16_emitcode("mov","a,%s",l);
9246       pic16_aopPut(AOP(result),"a",offr);
9247     } else {
9248       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9249       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9250     }
9251   }
9252 }
9253
9254 /*-----------------------------------------------------------------*/
9255 /* shiftL2Left2Result - shift left two bytes from left to result   */
9256 /*-----------------------------------------------------------------*/
9257 static void shiftL2Left2Result (operand *left, int offl,
9258                                 operand *result, int offr, int shCount)
9259 {
9260   int same = pic16_sameRegs(AOP(result), AOP(left));
9261   int i;
9262
9263   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9264
9265   if (same && (offl != offr)) { // shift bytes
9266     if (offr > offl) {
9267        for(i=1;i>-1;i--) {
9268          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9269          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9270        }
9271     } else { // just treat as different later on
9272                 same = 0;
9273     }
9274   }
9275
9276   if(same) {
9277     switch(shCount) {
9278     case 0:
9279       break;
9280     case 1:
9281     case 2:
9282     case 3:
9283
9284       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9285       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9286       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9287
9288       while(--shCount) {
9289                 emitCLRC;
9290                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9291                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9292       }
9293
9294       break;
9295     case 4:
9296     case 5:
9297       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9298       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9299       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9300       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9301       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9302       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9303       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9304       if(shCount >=5) {
9305                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9306                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9307       }
9308       break;
9309     case 6:
9310       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9311       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9312       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9313       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9314       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9315       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9316       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9317       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9318       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9319       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9320       break;
9321     case 7:
9322       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9323       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9324       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9325       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9326       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9327     }
9328
9329   } else {
9330     switch(shCount) {
9331     case 0:
9332       break;
9333     case 1:
9334     case 2:
9335     case 3:
9336       /* note, use a mov/add for the shift since the mov has a
9337          chance of getting optimized out */
9338       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9339       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9340       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9341       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9342       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9343
9344       while(--shCount) {
9345                 emitCLRC;
9346                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9347                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9348       }
9349       break;
9350
9351     case 4:
9352     case 5:
9353       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9354       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9355       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9356       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9357       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9358       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9359       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9360       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9361
9362
9363       if(shCount == 5) {
9364                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9365                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9366       }
9367       break;
9368     case 6:
9369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9370       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9372       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9373
9374       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9375       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9376       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9377       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9378       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9379       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9380       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9381       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9382       break;
9383     case 7:
9384       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9385       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9386       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9387       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9388       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9389     }
9390   }
9391
9392 }
9393 /*-----------------------------------------------------------------*/
9394 /* shiftR2Left2Result - shift right two bytes from left to result  */
9395 /*-----------------------------------------------------------------*/
9396 static void shiftR2Left2Result (operand *left, int offl,
9397                                 operand *result, int offr,
9398                                 int shCount, int sign)
9399 {
9400   int same = pic16_sameRegs(AOP(result), AOP(left));
9401   int i;
9402   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9403
9404   if (same && (offl != offr)) { // shift right bytes
9405     if (offr < offl) {
9406        for(i=0;i<2;i++) {
9407          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9408          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9409        }
9410     } else { // just treat as different later on
9411                 same = 0;
9412     }
9413   }
9414
9415   switch(shCount) {
9416   case 0:
9417     break;
9418   case 1:
9419   case 2:
9420   case 3:
9421     if(sign)
9422       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9423     else
9424       emitCLRC;
9425
9426     if(same) {
9427       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9428       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9429     } else {
9430       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9431       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9432       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9433       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9434     }
9435
9436     while(--shCount) {
9437       if(sign)
9438                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9439       else
9440                 emitCLRC;
9441       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9442       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9443     }
9444     break;
9445   case 4:
9446   case 5:
9447     if(same) {
9448
9449       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9450       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9451       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9452
9453       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9454       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9455       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9456       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9457     } else {
9458       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9459       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9460       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9461
9462       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9463       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9464       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9465       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9466       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9467     }
9468
9469     if(shCount >=5) {
9470       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9471       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9472     }
9473
9474     if(sign) {
9475       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9476       pic16_emitpcode(POC_BTFSC, 
9477                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9478       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9479     }
9480
9481     break;
9482
9483   case 6:
9484     if(same) {
9485
9486       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9487       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9488
9489       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9490       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9491       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9492       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9493       if(sign) {
9494         pic16_emitpcode(POC_BTFSC, 
9495                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9496         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9497       }
9498       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9499       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9500       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9501       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9502     } else {
9503       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9504       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9505       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9506       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9507       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9508       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9509       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9510       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9511       if(sign) {
9512         pic16_emitpcode(POC_BTFSC, 
9513                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9514         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9515       }
9516       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9517       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9518
9519         
9520     }
9521
9522     break;
9523   case 7:
9524     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9525     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9526     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9527     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9528     if(sign) {
9529       emitSKPNC;
9530       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9531     } else 
9532       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9533   }
9534 }
9535
9536
9537 /*-----------------------------------------------------------------*/
9538 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9539 /*-----------------------------------------------------------------*/
9540 static void shiftLLeftOrResult (operand *left, int offl,
9541                                 operand *result, int offr, int shCount)
9542 {
9543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544
9545     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9546     /* shift left accumulator */
9547     AccLsh(shCount);
9548     /* or with result */
9549     /* back to result */
9550     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9551 }
9552
9553 /*-----------------------------------------------------------------*/
9554 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9555 /*-----------------------------------------------------------------*/
9556 static void shiftRLeftOrResult (operand *left, int offl,
9557                                 operand *result, int offr, int shCount)
9558 {
9559     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9560     
9561     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9562     /* shift right accumulator */
9563     AccRsh(shCount, 1);
9564     /* or with result */
9565     /* back to result */
9566     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9567 }
9568
9569 /*-----------------------------------------------------------------*/
9570 /* genlshOne - left shift a one byte quantity by known count       */
9571 /*-----------------------------------------------------------------*/
9572 static void genlshOne (operand *result, operand *left, int shCount)
9573 {       
9574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9575     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9576 }
9577
9578 /*-----------------------------------------------------------------*/
9579 /* genlshTwo - left shift two bytes by known amount != 0           */
9580 /*-----------------------------------------------------------------*/
9581 static void genlshTwo (operand *result,operand *left, int shCount)
9582 {
9583     int size;
9584     
9585     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9586     size = pic16_getDataSize(result);
9587
9588     /* if shCount >= 8 */
9589     if (shCount >= 8) {
9590         shCount -= 8 ;
9591
9592         if (size > 1){
9593             if (shCount)
9594                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9595             else 
9596                 movLeft2Result(left, LSB, result, MSB16);
9597         }
9598         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9599     }
9600
9601     /*  1 <= shCount <= 7 */
9602     else {  
9603         if(size == 1)
9604             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9605         else 
9606             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9607     }
9608 }
9609
9610 /*-----------------------------------------------------------------*/
9611 /* shiftLLong - shift left one long from left to result            */
9612 /* offr = LSB or MSB16                                             */
9613 /*-----------------------------------------------------------------*/
9614 static void shiftLLong (operand *left, operand *result, int offr )
9615 {
9616     int size = AOP_SIZE(result);
9617     int same = pic16_sameRegs(AOP(left),AOP(result));
9618         int i;
9619
9620     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9621
9622         if (same && (offr == MSB16)) { //shift one byte
9623                 for(i=size-1;i>=MSB16;i--) {
9624                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9625                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9626                 }
9627         } else {
9628                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9629         }
9630         
9631     if (size > LSB+offr ){
9632                 if (same) {
9633                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9634                 } else {
9635                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9636                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9637                 }
9638          }
9639
9640     if(size > MSB16+offr){
9641                 if (same) {
9642                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9643                 } else {
9644                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9645                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9646                 }
9647     }
9648
9649     if(size > MSB24+offr){
9650                 if (same) {
9651                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9652                 } else {
9653                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9654                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9655                 }
9656     }
9657
9658     if(size > MSB32+offr){
9659                 if (same) {
9660                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9661                 } else {
9662                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9663                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9664                 }
9665     }
9666     if(offr != LSB)
9667                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668
9669 }
9670
9671 /*-----------------------------------------------------------------*/
9672 /* genlshFour - shift four byte by a known amount != 0             */
9673 /*-----------------------------------------------------------------*/
9674 static void genlshFour (operand *result, operand *left, int shCount)
9675 {
9676     int size;
9677
9678     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9679     size = AOP_SIZE(result);
9680
9681     /* if shifting more that 3 bytes */
9682     if (shCount >= 24 ) {
9683         shCount -= 24;
9684         if (shCount)
9685             /* lowest order of left goes to the highest
9686             order of the destination */
9687             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9688         else
9689             movLeft2Result(left, LSB, result, MSB32);
9690
9691                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9692                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9693                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9694
9695         return;
9696     }
9697
9698     /* more than two bytes */
9699     else if ( shCount >= 16 ) {
9700         /* lower order two bytes goes to higher order two bytes */
9701         shCount -= 16;
9702         /* if some more remaining */
9703         if (shCount)
9704             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9705         else {
9706             movLeft2Result(left, MSB16, result, MSB32);
9707             movLeft2Result(left, LSB, result, MSB24);
9708         }
9709                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9710                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9711         return;
9712     }    
9713
9714     /* if more than 1 byte */
9715     else if ( shCount >= 8 ) {
9716         /* lower order three bytes goes to higher order  three bytes */
9717         shCount -= 8;
9718         if(size == 2){
9719             if(shCount)
9720                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9721             else
9722                 movLeft2Result(left, LSB, result, MSB16);
9723         }
9724         else{   /* size = 4 */
9725             if(shCount == 0){
9726                 movLeft2Result(left, MSB24, result, MSB32);
9727                 movLeft2Result(left, MSB16, result, MSB24);
9728                 movLeft2Result(left, LSB, result, MSB16);
9729                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9730             }
9731             else if(shCount == 1)
9732                 shiftLLong(left, result, MSB16);
9733             else{
9734                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9735                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9736                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9737                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9738             }
9739         }
9740     }
9741
9742     /* 1 <= shCount <= 7 */
9743     else if(shCount <= 3)
9744     { 
9745         shiftLLong(left, result, LSB);
9746         while(--shCount >= 1)
9747             shiftLLong(result, result, LSB);
9748     }
9749     /* 3 <= shCount <= 7, optimize */
9750     else{
9751         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9752         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9753         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9754     }
9755 }
9756
9757 /*-----------------------------------------------------------------*/
9758 /* genLeftShiftLiteral - left shifting by known count              */
9759 /*-----------------------------------------------------------------*/
9760 void pic16_genLeftShiftLiteral (operand *left,
9761                                  operand *right,
9762                                  operand *result,
9763                                  iCode *ic)
9764 {    
9765     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9766     int size;
9767
9768     FENTRY;
9769     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9770     pic16_freeAsmop(right,NULL,ic,TRUE);
9771
9772     pic16_aopOp(left,ic,FALSE);
9773     pic16_aopOp(result,ic,TRUE);
9774
9775     size = getSize(operandType(result));
9776
9777 #if VIEW_SIZE
9778     pic16_emitcode("; shift left ","result %d, left %d",size,
9779              AOP_SIZE(left));
9780 #endif
9781
9782     /* I suppose that the left size >= result size */
9783     if(shCount == 0){
9784         while(size--){
9785             movLeft2Result(left, size, result, size);
9786         }
9787     }
9788
9789     else if(shCount >= (size * 8))
9790         while(size--)
9791             pic16_aopPut(AOP(result),zero,size);
9792     else{
9793         switch (size) {
9794             case 1:
9795                 genlshOne (result,left,shCount);
9796                 break;
9797
9798             case 2:
9799             case 3:
9800                 genlshTwo (result,left,shCount);
9801                 break;
9802
9803             case 4:
9804                 genlshFour (result,left,shCount);
9805                 break;
9806         }
9807     }
9808     pic16_freeAsmop(left,NULL,ic,TRUE);
9809     pic16_freeAsmop(result,NULL,ic,TRUE);
9810 }
9811
9812 /*-----------------------------------------------------------------*
9813  * genMultiAsm - repeat assembly instruction for size of register.
9814  * if endian == 1, then the high byte (i.e base address + size of 
9815  * register) is used first else the low byte is used first;
9816  *-----------------------------------------------------------------*/
9817 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9818 {
9819
9820   int offset = 0;
9821
9822   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9823
9824   if(!reg)
9825     return;
9826
9827   if(!endian) {
9828     endian = 1;
9829   } else {
9830     endian = -1;
9831     offset = size-1;
9832   }
9833
9834   while(size--) {
9835     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9836     offset += endian;
9837   }
9838
9839 }
9840
9841 #if !(USE_GENERIC_SIGNED_SHIFT)
9842 /*-----------------------------------------------------------------*/
9843 /* genLeftShift - generates code for left shifting                 */
9844 /*-----------------------------------------------------------------*/
9845 static void genLeftShift (iCode *ic)
9846 {
9847   operand *left,*right, *result;
9848   int size, offset;
9849 //  char *l;
9850   symbol *tlbl , *tlbl1;
9851   pCodeOp *pctemp;
9852
9853   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9854
9855   right = IC_RIGHT(ic);
9856   left  = IC_LEFT(ic);
9857   result = IC_RESULT(ic);
9858
9859   pic16_aopOp(right,ic,FALSE);
9860
9861   /* if the shift count is known then do it 
9862      as efficiently as possible */
9863   if (AOP_TYPE(right) == AOP_LIT) {
9864     pic16_genLeftShiftLiteral (left,right,result,ic);
9865     return ;
9866   }
9867
9868   /* shift count is unknown then we have to form
9869    * a loop. Get the loop count in WREG : Note: we take
9870    * only the lower order byte since shifting
9871    * more than 32 bits make no sense anyway, ( the
9872    * largest size of an object can be only 32 bits ) */
9873   
9874   pic16_aopOp(left,ic,FALSE);
9875   pic16_aopOp(result,ic,FALSE);
9876
9877   /* now move the left to the result if they are not the
9878    * same, and if size > 1,
9879    * and if right is not same to result (!!!) -- VR */
9880   if (!pic16_sameRegs(AOP(left),AOP(result))
9881       && (AOP_SIZE(result) > 1)) {
9882
9883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9884
9885     size = AOP_SIZE(result);
9886     offset=0;
9887     while (size--) {
9888
9889 #if 0
9890       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9891       if (*l == '@' && (IS_AOP_PREG(result))) {
9892
9893           pic16_emitcode("mov","a,%s",l);
9894           pic16_aopPut(AOP(result),"a",offset);
9895       } else
9896 #endif
9897       {
9898         /* we don't know if left is a literal or a register, take care -- VR */
9899         mov2f(AOP(result), AOP(left), offset);
9900       }
9901       offset++;
9902     }
9903   }
9904
9905   size = AOP_SIZE(result);
9906
9907   /* if it is only one byte then */
9908   if (size == 1) {
9909     if(optimized_for_speed) {
9910       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9911       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9912       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9913       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9914       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9915       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9916       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9917       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9918       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9919       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9920       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9921       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9922     } else {
9923
9924       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9925
9926       tlbl = newiTempLabel(NULL);
9927
9928 #if 1
9929       /* this is already done, why change it? */
9930       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9931                 mov2f(AOP(result), AOP(left), 0);
9932       }
9933 #endif
9934
9935       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9936       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9937       pic16_emitpLabel(tlbl->key);
9938       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9939       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9940       emitSKPC;
9941       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9942     }
9943     goto release ;
9944   }
9945     
9946   if (pic16_sameRegs(AOP(left),AOP(result))) {
9947
9948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9949     
9950     tlbl = newiTempLabel(NULL);
9951     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9952     genMultiAsm(POC_RRCF, result, size,1);
9953     pic16_emitpLabel(tlbl->key);
9954     genMultiAsm(POC_RLCF, result, size,0);
9955     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9956     emitSKPC;
9957     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9958     goto release;
9959   }
9960
9961   //tlbl = newiTempLabel(NULL);
9962   //offset = 0 ;   
9963   //tlbl1 = newiTempLabel(NULL);
9964
9965   //reAdjustPreg(AOP(result));    
9966     
9967   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9968   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9969   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9970   //MOVA(l);
9971   //pic16_emitcode("add","a,acc");         
9972   //pic16_aopPut(AOP(result),"a",offset++);
9973   //while (--size) {
9974   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9975   //  MOVA(l);
9976   //  pic16_emitcode("rlc","a");         
9977   //  pic16_aopPut(AOP(result),"a",offset++);
9978   //}
9979   //reAdjustPreg(AOP(result));
9980
9981   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9982   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9983
9984
9985   tlbl = newiTempLabel(NULL);
9986   tlbl1= newiTempLabel(NULL);
9987
9988   size = AOP_SIZE(result);
9989   offset = 1;
9990
9991   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9992
9993   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9994
9995   /* offset should be 0, 1 or 3 */
9996   
9997   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9998   emitSKPNZ;
9999   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10000
10001   pic16_emitpcode(POC_MOVWF, pctemp);
10002
10003
10004   pic16_emitpLabel(tlbl->key);
10005
10006   emitCLRC;
10007   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10008   while(--size)
10009     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10010
10011   pic16_emitpcode(POC_DECFSZ,  pctemp);
10012   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10013   pic16_emitpLabel(tlbl1->key);
10014
10015   pic16_popReleaseTempReg(pctemp,1);
10016
10017
10018  release:
10019   pic16_freeAsmop (right,NULL,ic,TRUE);
10020   pic16_freeAsmop(left,NULL,ic,TRUE);
10021   pic16_freeAsmop(result,NULL,ic,TRUE);
10022 }
10023 #endif
10024
10025
10026 #if 0
10027 #error old code (left here for reference)
10028 /*-----------------------------------------------------------------*/
10029 /* genLeftShift - generates code for left shifting                 */
10030 /*-----------------------------------------------------------------*/
10031 static void genLeftShift (iCode *ic)
10032 {
10033   operand *left,*right, *result;
10034   int size, offset;
10035   char *l;
10036   symbol *tlbl , *tlbl1;
10037   pCodeOp *pctemp;
10038
10039   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10040
10041   right = IC_RIGHT(ic);
10042   left  = IC_LEFT(ic);
10043   result = IC_RESULT(ic);
10044
10045   pic16_aopOp(right,ic,FALSE);
10046
10047   /* if the shift count is known then do it 
10048      as efficiently as possible */
10049   if (AOP_TYPE(right) == AOP_LIT) {
10050     pic16_genLeftShiftLiteral (left,right,result,ic);
10051     return ;
10052   }
10053
10054   /* shift count is unknown then we have to form 
10055      a loop get the loop count in B : Note: we take
10056      only the lower order byte since shifting
10057      more that 32 bits make no sense anyway, ( the
10058      largest size of an object can be only 32 bits ) */  
10059
10060     
10061   pic16_aopOp(left,ic,FALSE);
10062   pic16_aopOp(result,ic,FALSE);
10063
10064   /* now move the left to the result if they are not the
10065      same */
10066   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10067       AOP_SIZE(result) > 1) {
10068
10069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10070
10071     size = AOP_SIZE(result);
10072     offset=0;
10073     while (size--) {
10074       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10075       if (*l == '@' && (IS_AOP_PREG(result))) {
10076
10077         pic16_emitcode("mov","a,%s",l);
10078         pic16_aopPut(AOP(result),"a",offset);
10079       } else {
10080
10081         /* we don't know if left is a literal or a register, take care -- VR */
10082         mov2f(AOP(result), AOP(left), offset);
10083       }
10084       offset++;
10085     }
10086   }
10087
10088   size = AOP_SIZE(result);
10089
10090   /* if it is only one byte then */
10091   if (size == 1) {
10092     if(optimized_for_speed) {
10093       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10094       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10095       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10096       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10097       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10098       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10099       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10100       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10101       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10102       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10103       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10104       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10105     } else {
10106
10107       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10108
10109       tlbl = newiTempLabel(NULL);
10110       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10111                 mov2f(AOP(result), AOP(left), 0);
10112                 
10113 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10114 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10115       }
10116
10117       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10118       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10119       pic16_emitpLabel(tlbl->key);
10120       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10121       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10122       emitSKPC;
10123       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10124     }
10125     goto release ;
10126   }
10127     
10128   if (pic16_sameRegs(AOP(left),AOP(result))) {
10129
10130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10131     
10132     tlbl = newiTempLabel(NULL);
10133     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10134     genMultiAsm(POC_RRCF, result, size,1);
10135     pic16_emitpLabel(tlbl->key);
10136     genMultiAsm(POC_RLCF, result, size,0);
10137     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10138     emitSKPC;
10139     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10140     goto release;
10141   }
10142
10143   //tlbl = newiTempLabel(NULL);
10144   //offset = 0 ;   
10145   //tlbl1 = newiTempLabel(NULL);
10146
10147   //reAdjustPreg(AOP(result));    
10148     
10149   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10150   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10151   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10152   //MOVA(l);
10153   //pic16_emitcode("add","a,acc");         
10154   //pic16_aopPut(AOP(result),"a",offset++);
10155   //while (--size) {
10156   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10157   //  MOVA(l);
10158   //  pic16_emitcode("rlc","a");         
10159   //  pic16_aopPut(AOP(result),"a",offset++);
10160   //}
10161   //reAdjustPreg(AOP(result));
10162
10163   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10164   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10165
10166
10167   tlbl = newiTempLabel(NULL);
10168   tlbl1= newiTempLabel(NULL);
10169
10170   size = AOP_SIZE(result);
10171   offset = 1;
10172
10173   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10174
10175   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10176
10177   /* offset should be 0, 1 or 3 */
10178   
10179   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10180   emitSKPNZ;
10181   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10182
10183   pic16_emitpcode(POC_MOVWF, pctemp);
10184
10185
10186   pic16_emitpLabel(tlbl->key);
10187
10188   emitCLRC;
10189   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10190   while(--size)
10191     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10192
10193   pic16_emitpcode(POC_DECFSZ,  pctemp);
10194   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10195   pic16_emitpLabel(tlbl1->key);
10196
10197   pic16_popReleaseTempReg(pctemp,1);
10198
10199
10200  release:
10201   pic16_freeAsmop (right,NULL,ic,TRUE);
10202   pic16_freeAsmop(left,NULL,ic,TRUE);
10203   pic16_freeAsmop(result,NULL,ic,TRUE);
10204 }
10205 #endif
10206
10207 /*-----------------------------------------------------------------*/
10208 /* genrshOne - right shift a one byte quantity by known count      */
10209 /*-----------------------------------------------------------------*/
10210 static void genrshOne (operand *result, operand *left,
10211                        int shCount, int sign)
10212 {
10213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10214     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10215 }
10216
10217 /*-----------------------------------------------------------------*/
10218 /* genrshTwo - right shift two bytes by known amount != 0          */
10219 /*-----------------------------------------------------------------*/
10220 static void genrshTwo (operand *result,operand *left,
10221                        int shCount, int sign)
10222 {
10223   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10224   /* if shCount >= 8 */
10225   if (shCount >= 8) {
10226     shCount -= 8 ;
10227     if (shCount)
10228       shiftR1Left2Result(left, MSB16, result, LSB,
10229                          shCount, sign);
10230     else
10231       movLeft2Result(left, MSB16, result, LSB);
10232
10233     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10234
10235     if(sign) {
10236       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10237       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10238     }
10239   }
10240
10241   /*  1 <= shCount <= 7 */
10242   else
10243     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10244 }
10245
10246 /*-----------------------------------------------------------------*/
10247 /* shiftRLong - shift right one long from left to result           */
10248 /* offl = LSB or MSB16                                             */
10249 /*-----------------------------------------------------------------*/
10250 static void shiftRLong (operand *left, int offl,
10251                         operand *result, int sign)
10252 {
10253     int size = AOP_SIZE(result);
10254     int same = pic16_sameRegs(AOP(left),AOP(result));
10255     int i;
10256     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10257
10258         if (same && (offl == MSB16)) { //shift one byte right
10259                 for(i=MSB16;i<size;i++) {
10260                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10261                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10262                 }
10263         }
10264
10265     if(sign)
10266                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10267         else
10268                 emitCLRC;
10269
10270         if (same) {
10271                 if (offl == LSB)
10272                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10273         } else {
10274         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10275         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10276         }
10277
10278     if(offl == MSB16) {
10279         /* add sign of "a" */
10280         pic16_addSign(result, MSB32, sign);
10281         }
10282
10283         if (same) {
10284         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10285         } else {
10286         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10287         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10288         }
10289         
10290         if (same) {
10291         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10292         } else {
10293         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10294         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10295         }
10296
10297         if (same) {
10298         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10299         } else {
10300         if(offl == LSB){
10301                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10302                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10303         }
10304         }
10305 }
10306
10307 /*-----------------------------------------------------------------*/
10308 /* genrshFour - shift four byte by a known amount != 0             */
10309 /*-----------------------------------------------------------------*/
10310 static void genrshFour (operand *result, operand *left,
10311                         int shCount, int sign)
10312 {
10313   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10314   /* if shifting more that 3 bytes */
10315   if(shCount >= 24 ) {
10316     shCount -= 24;
10317     if(shCount)
10318       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10319     else
10320       movLeft2Result(left, MSB32, result, LSB);
10321
10322     pic16_addSign(result, MSB16, sign);
10323   }
10324   else if(shCount >= 16){
10325     shCount -= 16;
10326     if(shCount)
10327       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10328     else{
10329       movLeft2Result(left, MSB24, result, LSB);
10330       movLeft2Result(left, MSB32, result, MSB16);
10331     }
10332     pic16_addSign(result, MSB24, sign);
10333   }
10334   else if(shCount >= 8){
10335     shCount -= 8;
10336     if(shCount == 1)
10337       shiftRLong(left, MSB16, result, sign);
10338     else if(shCount == 0){
10339       movLeft2Result(left, MSB16, result, LSB);
10340       movLeft2Result(left, MSB24, result, MSB16);
10341       movLeft2Result(left, MSB32, result, MSB24);
10342       pic16_addSign(result, MSB32, sign);
10343     }
10344     else{ //shcount >= 2
10345       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10346       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10347       /* the last shift is signed */
10348       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10349       pic16_addSign(result, MSB32, sign);
10350     }
10351   }
10352   else{   /* 1 <= shCount <= 7 */
10353     if(shCount <= 2){
10354       shiftRLong(left, LSB, result, sign);
10355       if(shCount == 2)
10356         shiftRLong(result, LSB, result, sign);
10357     }
10358     else{
10359       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10360       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10361       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10362     }
10363   }
10364 }
10365
10366 /*-----------------------------------------------------------------*/
10367 /* genRightShiftLiteral - right shifting by known count            */
10368 /*-----------------------------------------------------------------*/
10369 static void genRightShiftLiteral (operand *left,
10370                                   operand *right,
10371                                   operand *result,
10372                                   iCode *ic,
10373                                   int sign)
10374 {    
10375   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10376   int lsize,res_size;
10377
10378   pic16_freeAsmop(right,NULL,ic,TRUE);
10379
10380   pic16_aopOp(left,ic,FALSE);
10381   pic16_aopOp(result,ic,TRUE);
10382
10383   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10384
10385 #if VIEW_SIZE
10386   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10387                  AOP_SIZE(left));
10388 #endif
10389
10390   lsize = pic16_getDataSize(left);
10391   res_size = pic16_getDataSize(result);
10392   /* test the LEFT size !!! */
10393
10394   /* I suppose that the left size >= result size */
10395   if(shCount == 0){
10396     assert (res_size <= lsize);
10397     while (res_size--) {
10398       mov2f (AOP(result), AOP(left), res_size);
10399     } // for
10400   }
10401
10402   else if(shCount >= (lsize * 8)){
10403
10404     if(res_size == 1) {
10405       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10406       if(sign) {
10407         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10408         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10409       }
10410     } else {
10411
10412       if(sign) {
10413         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10414         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10415         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10416         while(res_size--)
10417           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10418
10419       } else {
10420
10421         while(res_size--)
10422           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10423       }
10424     }
10425   } else {
10426
10427     switch (res_size) {
10428     case 1:
10429       genrshOne (result,left,shCount,sign);
10430       break;
10431
10432     case 2:
10433       genrshTwo (result,left,shCount,sign);
10434       break;
10435
10436     case 4:
10437       genrshFour (result,left,shCount,sign);
10438       break;
10439     default :
10440       break;
10441     }
10442
10443   }
10444
10445   pic16_freeAsmop(left,NULL,ic,TRUE);
10446   pic16_freeAsmop(result,NULL,ic,TRUE);
10447 }
10448
10449 #if !(USE_GENERIC_SIGNED_SHIFT)
10450 /*-----------------------------------------------------------------*/
10451 /* genSignedRightShift - right shift of signed number              */
10452 /*-----------------------------------------------------------------*/
10453 static void genSignedRightShift (iCode *ic)
10454 {
10455   operand *right, *left, *result;
10456   int size, offset;
10457   //  char *l;
10458   symbol *tlbl, *tlbl1 ;
10459   pCodeOp *pctemp;
10460
10461   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10462
10463   /* we do it the hard way put the shift count in b
10464      and loop thru preserving the sign */
10465   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10466
10467   right = IC_RIGHT(ic);
10468   left  = IC_LEFT(ic);
10469   result = IC_RESULT(ic);
10470
10471   pic16_aopOp(right,ic,FALSE);  
10472   pic16_aopOp(left,ic,FALSE);
10473   pic16_aopOp(result,ic,FALSE);
10474
10475
10476   if ( AOP_TYPE(right) == AOP_LIT) {
10477     genRightShiftLiteral (left,right,result,ic,1);
10478     return ;
10479   }
10480   /* shift count is unknown then we have to form 
10481      a loop get the loop count in B : Note: we take
10482      only the lower order byte since shifting
10483      more that 32 bits make no sense anyway, ( the
10484      largest size of an object can be only 32 bits ) */  
10485
10486   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10487   //pic16_emitcode("inc","b");
10488   //pic16_freeAsmop (right,NULL,ic,TRUE);
10489   //pic16_aopOp(left,ic,FALSE);
10490   //pic16_aopOp(result,ic,FALSE);
10491
10492   /* now move the left to the result if they are not the
10493      same */
10494   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10495       AOP_SIZE(result) > 1) {
10496
10497     size = AOP_SIZE(result);
10498     offset=0;
10499     while (size--) { 
10500       /*
10501         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10502         if (*l == '@' && IS_AOP_PREG(result)) {
10503
10504         pic16_emitcode("mov","a,%s",l);
10505         pic16_aopPut(AOP(result),"a",offset);
10506         } else
10507         pic16_aopPut(AOP(result),l,offset);
10508       */
10509       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10510       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10511
10512       offset++;
10513     }
10514   }
10515
10516   /* mov the highest order bit to OVR */    
10517   tlbl = newiTempLabel(NULL);
10518   tlbl1= newiTempLabel(NULL);
10519
10520   size = AOP_SIZE(result);
10521   offset = size - 1;
10522
10523   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10524
10525   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10526
10527   /* offset should be 0, 1 or 3 */
10528   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10529   emitSKPNZ;
10530   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10531
10532   pic16_emitpcode(POC_MOVWF, pctemp);
10533
10534
10535   pic16_emitpLabel(tlbl->key);
10536
10537   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10538   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10539
10540   while(--size) {
10541     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10542   }
10543
10544   pic16_emitpcode(POC_DECFSZ,  pctemp);
10545   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10546   pic16_emitpLabel(tlbl1->key);
10547
10548   pic16_popReleaseTempReg(pctemp,1);
10549 #if 0
10550   size = AOP_SIZE(result);
10551   offset = size - 1;
10552   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10553   pic16_emitcode("rlc","a");
10554   pic16_emitcode("mov","ov,c");
10555   /* if it is only one byte then */
10556   if (size == 1) {
10557     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10558     MOVA(l);
10559     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10560     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10561     pic16_emitcode("mov","c,ov");
10562     pic16_emitcode("rrc","a");
10563     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10564     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10565     pic16_aopPut(AOP(result),"a",0);
10566     goto release ;
10567   }
10568
10569   reAdjustPreg(AOP(result));
10570   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10571   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10572   pic16_emitcode("mov","c,ov");
10573   while (size--) {
10574     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10575     MOVA(l);
10576     pic16_emitcode("rrc","a");         
10577     pic16_aopPut(AOP(result),"a",offset--);
10578   }
10579   reAdjustPreg(AOP(result));
10580   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10581   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10582
10583  release:
10584 #endif
10585
10586   pic16_freeAsmop(left,NULL,ic,TRUE);
10587   pic16_freeAsmop(result,NULL,ic,TRUE);
10588   pic16_freeAsmop(right,NULL,ic,TRUE);
10589 }
10590 #endif
10591
10592 #if !(USE_GENERIC_SIGNED_SHIFT)
10593 #warning This implementation of genRightShift() is incomplete!
10594 /*-----------------------------------------------------------------*/
10595 /* genRightShift - generate code for right shifting                */
10596 /*-----------------------------------------------------------------*/
10597 static void genRightShift (iCode *ic)
10598 {
10599     operand *right, *left, *result;
10600     sym_link *letype ;
10601     int size, offset;
10602     char *l;
10603     symbol *tlbl, *tlbl1 ;
10604
10605     /* if signed then we do it the hard way preserve the
10606     sign bit moving it inwards */
10607     letype = getSpec(operandType(IC_LEFT(ic)));
10608     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10609
10610     if (!SPEC_USIGN(letype)) {
10611         genSignedRightShift (ic);
10612         return ;
10613     }
10614
10615     /* signed & unsigned types are treated the same : i.e. the
10616     signed is NOT propagated inwards : quoting from the
10617     ANSI - standard : "for E1 >> E2, is equivalent to division
10618     by 2**E2 if unsigned or if it has a non-negative value,
10619     otherwise the result is implementation defined ", MY definition
10620     is that the sign does not get propagated */
10621
10622     right = IC_RIGHT(ic);
10623     left  = IC_LEFT(ic);
10624     result = IC_RESULT(ic);
10625
10626     pic16_aopOp(right,ic,FALSE);
10627
10628     /* if the shift count is known then do it 
10629     as efficiently as possible */
10630     if (AOP_TYPE(right) == AOP_LIT) {
10631         genRightShiftLiteral (left,right,result,ic, 0);
10632         return ;
10633     }
10634
10635     /* shift count is unknown then we have to form 
10636     a loop get the loop count in B : Note: we take
10637     only the lower order byte since shifting
10638     more that 32 bits make no sense anyway, ( the
10639     largest size of an object can be only 32 bits ) */  
10640
10641     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10642     pic16_emitcode("inc","b");
10643     pic16_aopOp(left,ic,FALSE);
10644     pic16_aopOp(result,ic,FALSE);
10645
10646     /* now move the left to the result if they are not the
10647     same */
10648     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10649         AOP_SIZE(result) > 1) {
10650
10651         size = AOP_SIZE(result);
10652         offset=0;
10653         while (size--) {
10654             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10655             if (*l == '@' && IS_AOP_PREG(result)) {
10656
10657                 pic16_emitcode("mov","a,%s",l);
10658                 pic16_aopPut(AOP(result),"a",offset);
10659             } else
10660                 pic16_aopPut(AOP(result),l,offset);
10661             offset++;
10662         }
10663     }
10664
10665     tlbl = newiTempLabel(NULL);
10666     tlbl1= newiTempLabel(NULL);
10667     size = AOP_SIZE(result);
10668     offset = size - 1;
10669
10670     /* if it is only one byte then */
10671     if (size == 1) {
10672
10673       tlbl = newiTempLabel(NULL);
10674       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10675         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10676         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10677       }
10678
10679       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10680       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10681       pic16_emitpLabel(tlbl->key);
10682       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10683       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10684       emitSKPC;
10685       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10686
10687       goto release ;
10688     }
10689
10690     reAdjustPreg(AOP(result));
10691     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10692     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10693     CLRC;
10694     while (size--) {
10695         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10696         MOVA(l);
10697         pic16_emitcode("rrc","a");         
10698         pic16_aopPut(AOP(result),"a",offset--);
10699     }
10700     reAdjustPreg(AOP(result));
10701
10702     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10703     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10704
10705 release:
10706     pic16_freeAsmop(left,NULL,ic,TRUE);
10707     pic16_freeAsmop (right,NULL,ic,TRUE);
10708     pic16_freeAsmop(result,NULL,ic,TRUE);
10709 }
10710 #endif
10711
10712 #if (USE_GENERIC_SIGNED_SHIFT)
10713 /*-----------------------------------------------------------------*/
10714 /* genGenericShift - generates code for left or right shifting     */
10715 /*-----------------------------------------------------------------*/
10716 static void genGenericShift (iCode *ic, int isShiftLeft) {
10717   operand *left,*right, *result;
10718   int offset;
10719   int sign, signedCount;
10720   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10721   PIC_OPCODE pos_shift, neg_shift;
10722
10723   FENTRY;
10724
10725   right = IC_RIGHT(ic);
10726   left  = IC_LEFT(ic);
10727   result = IC_RESULT(ic);
10728
10729   pic16_aopOp(right,ic,FALSE);
10730   pic16_aopOp(left,ic,FALSE);
10731   pic16_aopOp(result,ic,TRUE);
10732
10733   sign = !SPEC_USIGN(operandType (left));
10734   signedCount = !SPEC_USIGN(operandType (right));
10735
10736   /* if the shift count is known then do it 
10737      as efficiently as possible */
10738   if (AOP_TYPE(right) == AOP_LIT) {
10739     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10740     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10741     // we should modify right->aopu.aop_lit here!
10742     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10743     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10744     if (isShiftLeft)
10745       pic16_genLeftShiftLiteral (left,right,result,ic);
10746     else
10747       genRightShiftLiteral (left,right,result,ic, sign);
10748
10749     goto release;
10750   } // if (right is literal)
10751
10752   /* shift count is unknown then we have to form a loop.
10753    * Note: we take only the lower order byte since shifting
10754    * more than 32 bits make no sense anyway, ( the
10755    * largest size of an object can be only 32 bits )
10756    * Note: we perform arithmetic shifts if the left operand is
10757    * signed and we do an (effective) right shift, i. e. we
10758    * shift in the sign bit from the left. */
10759    
10760   label_complete = newiTempLabel ( NULL );
10761   label_loop_pos = newiTempLabel ( NULL );
10762   label_loop_neg = NULL;
10763   label_negative = NULL;
10764   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10765   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10766
10767   if (signedCount) {
10768     // additional labels needed
10769     label_loop_neg = newiTempLabel ( NULL );
10770     label_negative = newiTempLabel ( NULL );
10771   } // if
10772
10773   // copy source to result -- this will effectively truncate the left operand to the size of result!
10774   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10775   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10776   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10777     mov2f (AOP(result),AOP(left), offset);
10778   } // for
10779
10780   // if result is longer than left, fill with zeros (or sign)
10781   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10782     if (sign && AOP_SIZE(left) > 0) {
10783       // shift signed operand -- fill with sign
10784       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10785       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10786       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10787       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10788         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10789       } // for
10790     } else {
10791       // shift unsigned operand -- fill result with zeros
10792       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10793         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10794       } // for
10795     }
10796   } // if (size mismatch)
10797
10798   pic16_mov2w (AOP(right), 0);
10799   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10800   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10801   
10802 #if 0
10803   // perform a shift by one (shift count is positive)
10804   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10805   // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3]          ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10806   pic16_emitpLabel (label_loop_pos->key);
10807   emitCLRC;
10808   if (sign && (pos_shift == POC_RRCF)) {
10809     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10810     emitSETC;
10811   } // if
10812   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10813   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10814   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10815 #else
10816   // perform a shift by one (shift count is positive)
10817   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10818   // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6]        ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10819   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10820   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10821   emitCLRC;
10822   pic16_emitpLabel (label_loop_pos->key);
10823   if (sign && (pos_shift == POC_RRCF)) {
10824     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10825     emitSETC;
10826   } // if
10827   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10828   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10829   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10830   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10831 #endif
10832
10833   if (signedCount) {
10834     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10835
10836     pic16_emitpLabel (label_negative->key);
10837     // perform a shift by -1 (shift count is negative)
10838     // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4                   ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10839     emitCLRC;
10840     pic16_emitpLabel (label_loop_neg->key);
10841     if (sign && (neg_shift == POC_RRCF)) {
10842       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10843       emitSETC;
10844     } // if
10845     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10846     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10847     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10848     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10849   } // if (signedCount)
10850
10851   pic16_emitpLabel (label_complete->key);
10852
10853 release:
10854   pic16_freeAsmop (right,NULL,ic,TRUE);
10855   pic16_freeAsmop(left,NULL,ic,TRUE);
10856   pic16_freeAsmop(result,NULL,ic,TRUE);
10857 }
10858
10859 static void genLeftShift (iCode *ic) {
10860   genGenericShift (ic, 1);
10861 }
10862
10863 static void genRightShift (iCode *ic) {
10864   genGenericShift (ic, 0);
10865 }
10866 #endif
10867
10868
10869 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10870 void pic16_loadFSR0(operand *op, int lit)
10871 {
10872   if(is_LitOp( op ) || lit) {
10873     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10874   } else {
10875     // set up FSR0 with address of result
10876     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10877     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10878   }
10879 }
10880
10881 /*-----------------------------------------------------------------*/
10882 /* genUnpackBits - generates code for unpacking bits               */
10883 /*-----------------------------------------------------------------*/
10884 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10885 {    
10886   int shCnt ;
10887   int rlen = 0 ;
10888   sym_link *etype, *letype;
10889   int blen=0, bstr=0;
10890   int lbstr;
10891   int offset = 0 ;
10892
10893     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10894     etype = getSpec(operandType(result));
10895     letype = getSpec(operandType(left));
10896     
10897 //    if(IS_BITFIELD(etype)) {
10898       blen = SPEC_BLEN(etype);
10899       bstr = SPEC_BSTR(etype);
10900 //    }
10901
10902     lbstr = SPEC_BSTR( letype );
10903
10904 #if 1
10905     if((blen == 1) && (bstr < 8)) {
10906       /* it is a single bit, so use the appropriate bit instructions */
10907       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10908
10909       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10910       
10911       if((ptype == POINTER) && (result)) {
10912         /* workaround to reduce the extra lfsr instruction */
10913         pic16_emitpcode(POC_BTFSC,
10914               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10915       } else {
10916         pic16_emitpcode(POC_BTFSC,
10917               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10918       }
10919         
10920       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10921
10922       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10923       return;
10924     }
10925
10926 #endif
10927
10928         /* the following call to pic16_loadFSR0 is temporary until
10929          * optimization to handle single bit assignments is added
10930          * to the function. Until then use the old safe way! -- VR */
10931         pic16_loadFSR0( left, 1 );
10932  
10933         /* read the first byte  */
10934         switch (ptype) {
10935                 case POINTER:
10936                 case IPOINTER:
10937                 case PPOINTER:
10938                 case FPOINTER:
10939                 case GPOINTER:
10940                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10941                         break;
10942                 case CPOINTER:
10943                         pic16_emitcode("clr","a");
10944                         pic16_emitcode("movc","a","@a+dptr");
10945                         break;
10946         }
10947         
10948
10949         /* if we have bitdisplacement then it fits   */
10950         /* into this byte completely or if length is */
10951         /* less than a byte                          */
10952         if ((shCnt = SPEC_BSTR(etype)) || 
10953                 (SPEC_BLEN(etype) <= 8))  {
10954
10955                 /* shift right acc */
10956                 AccRsh(shCnt, 0);
10957
10958                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10959                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10960
10961 /* VR -- normally I would use the following, but since we use the hack,
10962  * to avoid the masking from AccRsh, why not mask it right now? */
10963
10964 /*
10965                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10966 */
10967
10968                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10969           return ;
10970         }
10971
10972
10973
10974         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10975         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10976         exit(-1);
10977
10978     /* bit field did not fit in a byte  */
10979     rlen = SPEC_BLEN(etype) - 8;
10980     pic16_aopPut(AOP(result),"a",offset++);
10981
10982     while (1)  {
10983
10984         switch (ptype) {
10985         case POINTER:
10986         case IPOINTER:
10987             pic16_emitcode("inc","%s",rname);
10988             pic16_emitcode("mov","a,@%s",rname);
10989             break;
10990             
10991         case PPOINTER:
10992             pic16_emitcode("inc","%s",rname);
10993             pic16_emitcode("movx","a,@%s",rname);
10994             break;
10995
10996         case FPOINTER:
10997             pic16_emitcode("inc","dptr");
10998             pic16_emitcode("movx","a,@dptr");
10999             break;
11000             
11001         case CPOINTER:
11002             pic16_emitcode("clr","a");
11003             pic16_emitcode("inc","dptr");
11004             pic16_emitcode("movc","a","@a+dptr");
11005             break;
11006             
11007         case GPOINTER:
11008             pic16_emitcode("inc","dptr");
11009             pic16_emitcode("lcall","__gptrget");
11010             break;
11011         }
11012
11013         rlen -= 8;            
11014         /* if we are done */
11015         if ( rlen <= 0 )
11016             break ;
11017         
11018         pic16_aopPut(AOP(result),"a",offset++);
11019                               
11020     }
11021     
11022     if (rlen) {
11023         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11024         pic16_aopPut(AOP(result),"a",offset);          
11025     }
11026     
11027     return ;
11028 }
11029
11030
11031 static void genDataPointerGet(operand *left,
11032                               operand *result,
11033                               iCode *ic)
11034 {
11035   int size, offset = 0, leoffset=0 ;
11036
11037         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11038         pic16_aopOp(result, ic, TRUE);
11039
11040         size = AOP_SIZE(result);
11041 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11042
11043
11044 #if 0
11045         /* The following tests may save a redudant movff instruction when
11046          * accessing unions */
11047          
11048         /* if they are the same */
11049         if (operandsEqu (left, result)) {
11050                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11051                 goto release;
11052         }
11053 #endif
11054
11055 #if 0
11056         /* if they are the same registers */
11057         if (pic16_sameRegs(AOP(left),AOP(result))) {
11058                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11059                 goto release;
11060         }
11061 #endif
11062
11063 #if 1
11064         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11065                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11066                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11067                 goto release;
11068         }
11069 #endif
11070
11071
11072 #if 0
11073         if ( AOP_TYPE(left) == AOP_PCODE) {
11074                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11075                                 AOP(left)->aopu.pcop->name,
11076                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11077                                 PCOR(AOP(left)->aopu.pcop)->instance:
11078                                 PCOI(AOP(left)->aopu.pcop)->offset);
11079         }
11080 #endif
11081
11082         if(AOP(left)->aopu.pcop->type == PO_DIR)
11083                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11084
11085         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11086
11087         while (size--) {
11088                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11089                 
11090                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11091                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11092                         pic16_mov2w(AOP(left), offset); // patch 8
11093                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11094                 } else {
11095                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11096                                 pic16_popGet(AOP(left), offset), //patch 8
11097                                 pic16_popGet(AOP(result), offset)));
11098                 }
11099
11100                 offset++;
11101                 leoffset++;
11102         }
11103
11104 release:
11105     pic16_freeAsmop(result,NULL,ic,TRUE);
11106 }
11107
11108
11109
11110 /*-----------------------------------------------------------------*/
11111 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11112 /*-----------------------------------------------------------------*/
11113 static void genNearPointerGet (operand *left, 
11114                                operand *result, 
11115                                iCode *ic)
11116 {
11117 //  asmop *aop = NULL;
11118   //regs *preg = NULL ;
11119   sym_link *rtype, *retype;
11120   sym_link *ltype = operandType(left);    
11121
11122     FENTRY;
11123     
11124     rtype = operandType(result);
11125     retype= getSpec(rtype);
11126     
11127     pic16_aopOp(left,ic,FALSE);
11128
11129 //    pic16_DumpOp("(left)",left);
11130 //    pic16_DumpOp("(result)",result);
11131
11132     /* if left is rematerialisable and
11133      * result is not bit variable type and
11134      * the left is pointer to data space i.e
11135      * lower 128 bytes of space */
11136     
11137     if (AOP_TYPE(left) == AOP_PCODE
11138       && !IS_BITFIELD(retype)
11139       && DCL_TYPE(ltype) == POINTER) {
11140
11141         genDataPointerGet (left,result,ic);
11142         pic16_freeAsmop(left, NULL, ic, TRUE);
11143         return ;
11144     }
11145     
11146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11147     pic16_aopOp (result,ic,TRUE);
11148     
11149     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11150
11151 #if 1
11152     if(IS_BITFIELD( retype )
11153       && (SPEC_BLEN(operandType(result))==1)
11154     ) {
11155       iCode *nextic;
11156       pCodeOp *jop;
11157       int bitstrt, bytestrt;
11158
11159         /* if this is bitfield of size 1, see if we are checking the value
11160          * of a single bit in an if-statement,
11161          * if yes, then don't generate usual code, but execute the
11162          * genIfx directly -- VR */
11163
11164         nextic = ic->next;
11165
11166         /* CHECK: if next iCode is IFX
11167          * and current result operand is nextic's conditional operand
11168          * and current result operand live ranges ends at nextic's key number
11169          */
11170         if((nextic->op == IFX)
11171           && (result == IC_COND(nextic))
11172           && (OP_LIVETO(result) == nextic->seq)
11173           ) {
11174             /* everything is ok then */
11175             /* find a way to optimize the genIfx iCode */
11176
11177             bytestrt = SPEC_BSTR(operandType(result))/8;
11178             bitstrt = SPEC_BSTR(operandType(result))%8;
11179             
11180             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11181
11182             genIfxpCOpJump(nextic, jop);
11183             
11184             pic16_freeAsmop(left, NULL, ic, TRUE);
11185             pic16_freeAsmop(result, NULL, ic, TRUE);
11186             return;
11187         }
11188     }
11189 #endif
11190
11191
11192     /* if the value is already in a pointer register
11193      * then don't need anything more */
11194     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11195       /* otherwise get a free pointer register */
11196       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11197                 
11198       ;
11199     }
11200
11201     /* if bitfield then unpack the bits */
11202     if (IS_BITFIELD(retype)) 
11203       genUnpackBits (result, left, NULL, POINTER);
11204     else {
11205       /* we have can just get the values */
11206       int size = AOP_SIZE(result);
11207       int offset = 0;   
11208         
11209       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11210
11211       pic16_loadFSR0( left, 0 );
11212
11213       while(size--) {
11214         if(size) {
11215           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11216                 pic16_popGet(AOP(result), offset++)));
11217         } else {
11218           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11219                 pic16_popGet(AOP(result), offset++)));
11220         }
11221       }
11222     }
11223
11224 #if 0
11225     /* now some housekeeping stuff */
11226     if (aop) {
11227       /* we had to allocate for this iCode */
11228       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11229       pic16_freeAsmop(NULL,aop,ic,TRUE);
11230     } else { 
11231       /* we did not allocate which means left
11232        * already in a pointer register, then
11233        * if size > 0 && this could be used again
11234        * we have to point it back to where it 
11235        * belongs */
11236       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11237       if (AOP_SIZE(result) > 1
11238         && !OP_SYMBOL(left)->remat
11239         && ( OP_SYMBOL(left)->liveTo > ic->seq
11240             || ic->depth )) {
11241 //        int size = AOP_SIZE(result) - 1;
11242 //        while (size--)
11243 //          pic16_emitcode("dec","%s",rname);
11244         }
11245     }
11246 #endif
11247
11248     /* done */
11249     pic16_freeAsmop(left,NULL,ic,TRUE);
11250     pic16_freeAsmop(result,NULL,ic,TRUE);
11251 }
11252
11253 /*-----------------------------------------------------------------*/
11254 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11255 /*-----------------------------------------------------------------*/
11256 static void genPagedPointerGet (operand *left, 
11257                                operand *result, 
11258                                iCode *ic)
11259 {
11260     asmop *aop = NULL;
11261     regs *preg = NULL ;
11262     char *rname ;
11263     sym_link *rtype, *retype;    
11264
11265     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11266
11267     rtype = operandType(result);
11268     retype= getSpec(rtype);
11269     
11270     pic16_aopOp(left,ic,FALSE);
11271
11272   /* if the value is already in a pointer register
11273        then don't need anything more */
11274     if (!AOP_INPREG(AOP(left))) {
11275         /* otherwise get a free pointer register */
11276         aop = newAsmop(0);
11277         preg = getFreePtr(ic,&aop,FALSE);
11278         pic16_emitcode("mov","%s,%s",
11279                 preg->name,
11280                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11281         rname = preg->name ;
11282     } else
11283         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11284     
11285     pic16_freeAsmop(left,NULL,ic,TRUE);
11286     pic16_aopOp (result,ic,TRUE);
11287
11288     /* if bitfield then unpack the bits */
11289     if (IS_BITFIELD(retype)) 
11290         genUnpackBits (result,left,rname,PPOINTER);
11291     else {
11292         /* we have can just get the values */
11293         int size = AOP_SIZE(result);
11294         int offset = 0 ;        
11295         
11296         while (size--) {
11297             
11298             pic16_emitcode("movx","a,@%s",rname);
11299             pic16_aopPut(AOP(result),"a",offset);
11300             
11301             offset++ ;
11302             
11303             if (size)
11304                 pic16_emitcode("inc","%s",rname);
11305         }
11306     }
11307
11308     /* now some housekeeping stuff */
11309     if (aop) {
11310         /* we had to allocate for this iCode */
11311         pic16_freeAsmop(NULL,aop,ic,TRUE);
11312     } else { 
11313         /* we did not allocate which means left
11314            already in a pointer register, then
11315            if size > 0 && this could be used again
11316            we have to point it back to where it 
11317            belongs */
11318         if (AOP_SIZE(result) > 1 &&
11319             !OP_SYMBOL(left)->remat &&
11320             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11321               ic->depth )) {
11322             int size = AOP_SIZE(result) - 1;
11323             while (size--)
11324                 pic16_emitcode("dec","%s",rname);
11325         }
11326     }
11327
11328     /* done */
11329     pic16_freeAsmop(result,NULL,ic,TRUE);
11330     
11331         
11332 }
11333
11334 /*-----------------------------------------------------------------*/
11335 /* genFarPointerGet - gget value from far space                    */
11336 /*-----------------------------------------------------------------*/
11337 static void genFarPointerGet (operand *left,
11338                               operand *result, iCode *ic)
11339 {
11340     int size, offset ;
11341     sym_link *retype = getSpec(operandType(result));
11342
11343     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11344
11345     pic16_aopOp(left,ic,FALSE);
11346
11347     /* if the operand is already in dptr 
11348     then we do nothing else we move the value to dptr */
11349     if (AOP_TYPE(left) != AOP_STR) {
11350         /* if this is remateriazable */
11351         if (AOP_TYPE(left) == AOP_IMMD)
11352             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11353         else { /* we need to get it byte by byte */
11354             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11355             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11356             if (options.model == MODEL_FLAT24)
11357             {
11358                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11359             }
11360         }
11361     }
11362     /* so dptr know contains the address */
11363     pic16_freeAsmop(left,NULL,ic,TRUE);
11364     pic16_aopOp(result,ic,TRUE);
11365
11366     /* if bit then unpack */
11367     if (IS_BITFIELD(retype)) 
11368         genUnpackBits(result,left,"dptr",FPOINTER);
11369     else {
11370         size = AOP_SIZE(result);
11371         offset = 0 ;
11372
11373         while (size--) {
11374             pic16_emitcode("movx","a,@dptr");
11375             pic16_aopPut(AOP(result),"a",offset++);
11376             if (size)
11377                 pic16_emitcode("inc","dptr");
11378         }
11379     }
11380
11381     pic16_freeAsmop(result,NULL,ic,TRUE);
11382 }
11383
11384 #if 0
11385 /*-----------------------------------------------------------------*/
11386 /* genCodePointerGet - get value from code space                  */
11387 /*-----------------------------------------------------------------*/
11388 static void genCodePointerGet (operand *left,
11389                                 operand *result, iCode *ic)
11390 {
11391     int size, offset ;
11392     sym_link *retype = getSpec(operandType(result));
11393
11394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11395
11396     pic16_aopOp(left,ic,FALSE);
11397
11398     /* if the operand is already in dptr 
11399     then we do nothing else we move the value to dptr */
11400     if (AOP_TYPE(left) != AOP_STR) {
11401         /* if this is remateriazable */
11402         if (AOP_TYPE(left) == AOP_IMMD)
11403             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11404         else { /* we need to get it byte by byte */
11405             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11406             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11407             if (options.model == MODEL_FLAT24)
11408             {
11409                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11410             }
11411         }
11412     }
11413     /* so dptr know contains the address */
11414     pic16_freeAsmop(left,NULL,ic,TRUE);
11415     pic16_aopOp(result,ic,FALSE);
11416
11417     /* if bit then unpack */
11418     if (IS_BITFIELD(retype)) 
11419         genUnpackBits(result,left,"dptr",CPOINTER);
11420     else {
11421         size = AOP_SIZE(result);
11422         offset = 0 ;
11423
11424         while (size--) {
11425             pic16_emitcode("clr","a");
11426             pic16_emitcode("movc","a,@a+dptr");
11427             pic16_aopPut(AOP(result),"a",offset++);
11428             if (size)
11429                 pic16_emitcode("inc","dptr");
11430         }
11431     }
11432
11433     pic16_freeAsmop(result,NULL,ic,TRUE);
11434 }
11435 #endif
11436
11437 #if 0
11438 /*-----------------------------------------------------------------*/
11439 /* genGenPointerGet - gget value from generic pointer space        */
11440 /*-----------------------------------------------------------------*/
11441 static void genGenPointerGet (operand *left,
11442                               operand *result, iCode *ic)
11443 {
11444   int size, offset, lit;
11445   sym_link *retype = getSpec(operandType(result));
11446
11447         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11448         pic16_aopOp(left,ic,FALSE);
11449         pic16_aopOp(result,ic,FALSE);
11450         size = AOP_SIZE(result);
11451
11452         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11453
11454         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11455
11456                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11457                 // load FSR0 from immediate
11458                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11459
11460 //              pic16_loadFSR0( left );
11461
11462                 offset = 0;
11463                 while(size--) {
11464                         if(size) {
11465                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11466                         } else {
11467                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11468                         }
11469                         offset++;
11470                 }
11471                 goto release;
11472
11473         }
11474         else { /* we need to get it byte by byte */
11475                 // set up FSR0 with address from left
11476                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11477                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11478                 
11479                 offset = 0 ;
11480
11481                 while(size--) {
11482                         if(size) {
11483                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11484                         } else {
11485                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11486                         }
11487                         offset++;
11488                 }
11489                 goto release;
11490         }
11491
11492   /* if bit then unpack */
11493         if (IS_BITFIELD(retype)) 
11494                 genUnpackBits(result,left,"BAD",GPOINTER);
11495
11496         release:
11497         pic16_freeAsmop(left,NULL,ic,TRUE);
11498         pic16_freeAsmop(result,NULL,ic,TRUE);
11499
11500 }
11501 #endif
11502
11503
11504 /*-----------------------------------------------------------------*/
11505 /* genGenPointerGet - gget value from generic pointer space        */
11506 /*-----------------------------------------------------------------*/
11507 static void genGenPointerGet (operand *left,
11508                               operand *result, iCode *ic)
11509 {
11510   int size, offset, lit;
11511   sym_link *retype = getSpec(operandType(result));
11512   char fgptrget[32];
11513
11514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11515     pic16_aopOp(left,ic,FALSE);
11516     pic16_aopOp(result,ic,TRUE);
11517     size = AOP_SIZE(result);
11518
11519     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11520
11521     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11522
11523       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11524       // load FSR0 from immediate
11525       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11526
11527       werror(W_POSSBUG2, __FILE__, __LINE__);
11528
11529       offset = 0;
11530       while(size--) {
11531         if(size) {
11532           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11533         } else {
11534           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11535         }
11536         offset++;
11537       }
11538
11539       goto release;
11540
11541     } else { /* we need to get it byte by byte */
11542
11543       /* set up WREG:PRODL:FSR0L with address from left */
11544       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11545       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11546       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11547       
11548       switch( size ) {
11549         case 1: strcpy(fgptrget, "__gptrget1"); break;
11550         case 2: strcpy(fgptrget, "__gptrget2"); break;
11551         case 3: strcpy(fgptrget, "__gptrget3"); break;
11552         case 4: strcpy(fgptrget, "__gptrget4"); break;
11553         default:
11554           werror(W_POSSBUG2, __FILE__, __LINE__);
11555           abort();
11556       }
11557       
11558       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11559       
11560       assignResultValue(result, 1);
11561       
11562       {
11563         symbol *sym;
11564
11565           sym = newSymbol( fgptrget, 0 );
11566           sym->used++;
11567           strcpy(sym->rname, fgptrget);
11568           checkAddSym(&externs, sym);
11569
11570 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11571       }
11572               
11573       goto release;
11574     }
11575
11576   /* if bit then unpack */
11577     if (IS_BITFIELD(retype)) 
11578       genUnpackBits(result,left,"BAD",GPOINTER);
11579
11580 release:
11581   pic16_freeAsmop(left,NULL,ic,TRUE);
11582   pic16_freeAsmop(result,NULL,ic,TRUE);
11583 }
11584
11585 /*-----------------------------------------------------------------*/
11586 /* genConstPointerGet - get value from const generic pointer space */
11587 /*-----------------------------------------------------------------*/
11588 static void genConstPointerGet (operand *left,
11589                                 operand *result, iCode *ic)
11590 {
11591   //sym_link *retype = getSpec(operandType(result));
11592   // symbol *albl = newiTempLabel(NULL);        // patch 15
11593   // symbol *blbl = newiTempLabel(NULL);        //
11594   // PIC_OPCODE poc;                            // patch 15
11595   int size;
11596   int offset = 0;
11597
11598   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11599   pic16_aopOp(left,ic,FALSE);
11600   pic16_aopOp(result,ic,TRUE);
11601   size = AOP_SIZE(result);
11602
11603   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11604
11605   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11606
11607   // set up table pointer
11608   if( (AOP_TYPE(left) == AOP_PCODE) 
11609       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11610           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11611     {
11612       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11613       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11614       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11615       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11616       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11617       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11618   } else {
11619     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11620     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11621     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11622   }
11623
11624   while(size--) {
11625     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11626     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11627     offset++;
11628   }
11629     
11630   pic16_freeAsmop(left,NULL,ic,TRUE);
11631   pic16_freeAsmop(result,NULL,ic,TRUE);
11632 }
11633
11634
11635 /*-----------------------------------------------------------------*/
11636 /* genPointerGet - generate code for pointer get                   */
11637 /*-----------------------------------------------------------------*/
11638 static void genPointerGet (iCode *ic)
11639 {
11640   operand *left, *result ;
11641   sym_link *type, *etype;
11642   int p_type;
11643
11644     FENTRY;
11645     
11646     left = IC_LEFT(ic);
11647     result = IC_RESULT(ic) ;
11648
11649     /* depending on the type of pointer we need to
11650     move it to the correct pointer register */
11651     type = operandType(left);
11652     etype = getSpec(type);
11653
11654 #if 0
11655     if (IS_PTR_CONST(type))
11656 #else
11657     if (IS_CODEPTR(type))
11658 #endif
11659       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11660
11661     /* if left is of type of pointer then it is simple */
11662     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11663       p_type = DCL_TYPE(type);
11664     else {
11665       /* we have to go by the storage class */
11666       p_type = PTR_TYPE(SPEC_OCLS(etype));
11667
11668       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11669
11670       if (SPEC_OCLS(etype)->codesp ) {
11671         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11672         //p_type = CPOINTER ;   
11673       } else
11674       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11675         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11676         /*p_type = FPOINTER ;*/ 
11677       } else
11678       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11679         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11680         /* p_type = PPOINTER; */
11681       } else
11682       if (SPEC_OCLS(etype) == idata ) {
11683         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11684         /* p_type = IPOINTER; */
11685       } else {
11686         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11687         /* p_type = POINTER ; */
11688       }
11689     }
11690
11691     /* now that we have the pointer type we assign
11692     the pointer values */
11693     switch (p_type) {
11694       case POINTER:     
11695       case IPOINTER:
11696         genNearPointerGet (left,result,ic);
11697         break;
11698
11699       case PPOINTER:
11700         genPagedPointerGet(left,result,ic);
11701         break;
11702
11703       case FPOINTER:
11704         genFarPointerGet (left,result,ic);
11705         break;
11706
11707       case CPOINTER:
11708         genConstPointerGet (left,result,ic);
11709         //pic16_emitcodePointerGet (left,result,ic);
11710         break;
11711
11712       case GPOINTER:
11713 #if 0
11714       if (IS_PTR_CONST(type))
11715         genConstPointerGet (left,result,ic);
11716       else
11717 #endif
11718         genGenPointerGet (left,result,ic);
11719       break;
11720
11721     default:
11722       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11723               "genPointerGet: illegal pointer type");
11724     
11725     }
11726 }
11727
11728 /*-----------------------------------------------------------------*/
11729 /* genPackBits - generates code for packed bit storage             */
11730 /*-----------------------------------------------------------------*/
11731 static void genPackBits (sym_link    *etype , operand *result,
11732                          operand *right ,
11733                          char *rname, int p_type)
11734 {
11735   int shCnt = 0 ;
11736   int offset = 0  ;
11737   int rLen = 0 ;
11738   int blen, bstr ;   
11739   sym_link *retype;
11740
11741         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11742         blen = SPEC_BLEN(etype);
11743         bstr = SPEC_BSTR(etype);
11744
11745         retype = getSpec(operandType(right));
11746
11747         if(AOP_TYPE(right) == AOP_LIT) {
11748                 if((blen == 1) && (bstr < 8)) {
11749                   unsigned long lit;
11750                         /* it is a single bit, so use the appropriate bit instructions */
11751
11752                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11753
11754                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11755 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11756                         if((p_type == POINTER) && (result)) {
11757                                 /* workaround to reduce the extra lfsr instruction */
11758                                 if(lit) {
11759                                         pic16_emitpcode(POC_BSF,
11760                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11761                                 } else {
11762                                         pic16_emitpcode(POC_BCF,
11763                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11764                                 }
11765                         } else {
11766                                 pic16_loadFSR0(result, 1);
11767                                 if(lit) {
11768                                         pic16_emitpcode(POC_BSF,
11769                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11770                                 } else {
11771                                         pic16_emitpcode(POC_BCF,
11772                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11773                                 }
11774                         }
11775         
11776                   return;
11777                 }
11778                 /* move literal to W */
11779                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11780                 offset++;
11781         } else
11782         if(IS_BITFIELD(retype) 
11783           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11784           && (blen == 1)) {
11785           int rblen, rbstr;
11786
11787             rblen = SPEC_BLEN( retype );
11788             rbstr = SPEC_BSTR( retype );
11789             
11790
11791             if(IS_BITFIELD(etype)) {
11792               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11793               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11794             } else {
11795               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11796             }
11797             
11798             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11799             
11800             if(IS_BITFIELD(etype)) {
11801               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11802             } else {
11803               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11804             }
11805
11806             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11807             
11808             return;
11809         } else {
11810           /* move right to W */
11811           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11812         }
11813
11814         /* if the bit length is less than or   */
11815         /* it exactly fits a byte then         */
11816         if((shCnt=SPEC_BSTR(etype))
11817                 || SPEC_BLEN(etype) <= 8 )  {
11818                 int fsr0_setup = 0;
11819
11820                 if (blen != 8 || bstr != 0) {
11821                   // we need to combine the value with the old value
11822                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11823
11824           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11825                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11826                 
11827                   /* shift left acc */
11828                   AccLsh(shCnt);
11829
11830                   /* using PRODH as a temporary register here */
11831                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11832
11833                   /* get old value */
11834                   switch (p_type) {
11835                         case FPOINTER:
11836                         case POINTER:
11837                                 pic16_loadFSR0( result, 1 );
11838                                 fsr0_setup = 1;
11839                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11840 //                              pic16_emitcode ("mov","b,a");
11841 //                              pic16_emitcode("mov","a,@%s",rname);
11842                                 break;
11843
11844                         case GPOINTER:
11845                                 if (AOP(result)->aopu.aop_reg[2]) {
11846                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11847                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11848                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11849                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11850                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11851                                   {
11852                                     symbol *sym;
11853                                     sym = newSymbol( "__gptrget1", 0 );
11854                                     strcpy(sym->rname, "__gptrget1");
11855                                     checkAddSym(&externs, sym);
11856                                   }
11857                                 } else {
11858                                   // data pointer (just 2 byte given)
11859                                   pic16_loadFSR0( result, 1 );
11860                                   fsr0_setup = 1;
11861                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11862                                 }
11863                                 
11864                                 // warnings will be emitted below
11865                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11866                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11867                                 break;
11868
11869                         default:
11870                                 assert (0 && "invalid pointer type specified");
11871                                 break;
11872                   }
11873 #if 1
11874                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11875                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11876                                         (unsigned char)(0xff >> (8-bstr))) ));
11877                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11878                 } // if (blen != 8 || bstr != 0)
11879
11880                 /* write new value back */
11881                 switch (p_type) {
11882                         case FPOINTER:
11883                         case POINTER:
11884                                 if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11885                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11886                                 break;
11887
11888                         case GPOINTER:
11889                                 if (AOP(result)->aopu.aop_reg[2]) {
11890                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11891                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11892                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11893                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11894                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11895                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11896                                   {
11897                                     symbol *sym;
11898                                     sym = newSymbol( "__gptrput1", 0 );
11899                                     strcpy(sym->rname, "__gptrput1");
11900                                     checkAddSym(&externs, sym);
11901                                   }
11902                                 } else {
11903                                   // data pointer (just 2 byte given)
11904                                   if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11905                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11906                                 }
11907                                 
11908                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11909                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11910                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11911                                 break;
11912
11913                         default:
11914                                 assert (0 && "invalid pointer type specified");
11915                                 break;
11916                 }
11917 #endif
11918
11919           return;
11920         }
11921
11922
11923 #if 0
11924         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11925         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11926         exit(-1);
11927 #endif
11928
11929
11930     pic16_loadFSR0(result, 1);                  // load FSR0 with address of result
11931     rLen = SPEC_BLEN(etype)-8;
11932     
11933     /* now generate for lengths greater than one byte */
11934     while (1) {
11935         rLen -= 8 ;
11936         if (rLen <= 0 ) {
11937           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11938           break ;
11939         }
11940
11941         switch (p_type) {
11942             case POINTER:
11943                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11944                 break;
11945
11946 /*
11947             case FPOINTER:
11948                 MOVA(l);
11949                 pic16_emitcode("movx","@dptr,a");
11950                 break;
11951
11952             case GPOINTER:
11953                 MOVA(l);
11954                 DEBUGpic16_emitcode(";lcall","__gptrput");
11955                 break;  
11956 */
11957           default:
11958             assert(0);
11959         }   
11960
11961
11962         pic16_mov2w(AOP(right), offset++);
11963     }
11964
11965     /* last last was not complete */
11966     if (rLen)   {
11967         /* save the byte & read byte */
11968         switch (p_type) {
11969             case POINTER:
11970 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11971                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11972                 break;
11973
11974 /*
11975             case FPOINTER:
11976                 pic16_emitcode ("mov","b,a");
11977                 pic16_emitcode("movx","a,@dptr");
11978                 break;
11979
11980             case GPOINTER:
11981                 pic16_emitcode ("push","b");
11982                 pic16_emitcode ("push","acc");
11983                 pic16_emitcode ("lcall","__gptrget");
11984                 pic16_emitcode ("pop","b");
11985                 break;
11986 */
11987             default:
11988               assert(0);
11989         }
11990         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11991         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11992         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11993 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11994 //        pic16_emitcode ("orl","a,b");
11995     }
11996
11997 //    if (p_type == GPOINTER)
11998 //        pic16_emitcode("pop","b");
11999
12000     switch (p_type) {
12001
12002       case POINTER:
12003         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12004 //      pic16_emitcode("mov","@%s,a",rname);
12005         break;
12006 /*
12007       case FPOINTER:
12008         pic16_emitcode("movx","@dptr,a");
12009         break;
12010         
12011       case GPOINTER:
12012         DEBUGpic16_emitcode(";lcall","__gptrput");
12013         break;                  
12014 */
12015       default:
12016         assert(0);
12017     }
12018     
12019 //    pic16_freeAsmop(right, NULL, ic, TRUE);
12020 }
12021 /*-----------------------------------------------------------------*/
12022 /* genDataPointerSet - remat pointer to data space                 */
12023 /*-----------------------------------------------------------------*/
12024 static void genDataPointerSet(operand *right,
12025                               operand *result,
12026                               iCode *ic)
12027 {
12028     int size, offset = 0, resoffset=0 ;
12029
12030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12031     pic16_aopOp(right,ic,FALSE);
12032
12033     size = AOP_SIZE(right);
12034
12035 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12036
12037 #if 0
12038     if ( AOP_TYPE(result) == AOP_PCODE) {
12039       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12040               AOP(result)->aopu.pcop->name,
12041                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12042               PCOR(AOP(result)->aopu.pcop)->instance:
12043               PCOI(AOP(result)->aopu.pcop)->offset);
12044     }
12045 #endif
12046
12047         if(AOP(result)->aopu.pcop->type == PO_DIR)
12048                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12049
12050         while (size--) {
12051                 if (AOP_TYPE(right) == AOP_LIT) {
12052                   unsigned int lit;
12053
12054                     if(!IS_FLOAT(operandType( right )))
12055                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12056                     else {
12057                       union {
12058                         unsigned long lit_int;
12059                         float lit_float;
12060                       } info;
12061         
12062                         /* take care if literal is a float */
12063                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12064                         lit = info.lit_int;
12065                     }
12066
12067                     lit = lit >> (8*offset);
12068                     if(lit&0xff) {
12069                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12070                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12071                     } else {
12072                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12073                     }
12074                 } else {
12075                   pic16_mov2w(AOP(right), offset);
12076                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12077                 }
12078                 offset++;
12079                 resoffset++;
12080         }
12081
12082     pic16_freeAsmop(right,NULL,ic,TRUE);
12083 }
12084
12085
12086
12087 /*-----------------------------------------------------------------*/
12088 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12089 /*-----------------------------------------------------------------*/
12090 static void genNearPointerSet (operand *right,
12091                                operand *result, 
12092                                iCode *ic)
12093 {
12094   asmop *aop = NULL;
12095   sym_link *retype;
12096   sym_link *ptype = operandType(result);
12097   sym_link *resetype;
12098     
12099         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12100         retype= getSpec(operandType(right));
12101         resetype = getSpec(operandType(result));
12102   
12103         pic16_aopOp(result,ic,FALSE);
12104     
12105         /* if the result is rematerializable &
12106          * in data space & not a bit variable */
12107         
12108         /* and result is not a bit variable */
12109         if (AOP_TYPE(result) == AOP_PCODE
12110 //              && AOP_TYPE(result) == AOP_IMMD
12111                 && DCL_TYPE(ptype) == POINTER
12112                 && !IS_BITFIELD(retype)
12113                 && !IS_BITFIELD(resetype)) {
12114
12115                 genDataPointerSet (right,result,ic);
12116                 pic16_freeAsmop(result,NULL,ic,TRUE);
12117           return;
12118         }
12119
12120         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12121         pic16_aopOp(right,ic,FALSE);
12122         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12123
12124         /* if the value is already in a pointer register
12125          * then don't need anything more */
12126         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12127           /* otherwise get a free pointer register */
12128           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12129
12130           ;
12131         }
12132
12133         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12134
12135         /* if bitfield then unpack the bits */
12136         if (IS_BITFIELD(resetype)) {
12137                 genPackBits (resetype, result, right, NULL, POINTER);
12138         } else {
12139                 /* we have can just get the values */
12140           int size = AOP_SIZE(right);
12141           int offset = 0 ;    
12142
12143             pic16_loadFSR0(result, 0);
12144             
12145                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12146                 while (size--) {
12147                                 if (AOP_TYPE(right) == AOP_LIT) {
12148                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12149                                         if (size) {
12150                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12151                                         } else {
12152                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12153                                         }
12154                                 } else { // no literal
12155                                         if(size) {
12156                                                 pic16_emitpcode(POC_MOVFF,
12157                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12158                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12159                                         } else {
12160                                                 pic16_emitpcode(POC_MOVFF,
12161                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12162                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12163                                         }
12164                                 }
12165                         offset++;
12166                 }
12167         }
12168
12169         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12170         /* now some housekeeping stuff */
12171         if (aop) {
12172           /* we had to allocate for this iCode */
12173           pic16_freeAsmop(NULL,aop,ic,TRUE);
12174         } else { 
12175           /* we did not allocate which means left
12176            * already in a pointer register, then
12177            * if size > 0 && this could be used again
12178            * we have to point it back to where it 
12179            * belongs */
12180           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12181           if (AOP_SIZE(right) > 1
12182             && !OP_SYMBOL(result)->remat
12183             && ( OP_SYMBOL(result)->liveTo > ic->seq
12184             || ic->depth )) {
12185
12186               int size = AOP_SIZE(right) - 1;
12187
12188                 while (size--)
12189                   pic16_emitcode("decf","fsr0,f");
12190                   //pic16_emitcode("dec","%s",rname);
12191             }
12192         }
12193
12194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12195     /* done */
12196 //release:
12197     pic16_freeAsmop(right,NULL,ic,TRUE);
12198     pic16_freeAsmop(result,NULL,ic,TRUE);
12199 }
12200
12201 /*-----------------------------------------------------------------*/
12202 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12203 /*-----------------------------------------------------------------*/
12204 static void genPagedPointerSet (operand *right,
12205                                operand *result, 
12206                                iCode *ic)
12207 {
12208     asmop *aop = NULL;
12209     regs *preg = NULL ;
12210     char *rname , *l;
12211     sym_link *retype;
12212        
12213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12214
12215     retype= getSpec(operandType(right));
12216     
12217     pic16_aopOp(result,ic,FALSE);
12218     
12219     /* if the value is already in a pointer register
12220        then don't need anything more */
12221     if (!AOP_INPREG(AOP(result))) {
12222         /* otherwise get a free pointer register */
12223         aop = newAsmop(0);
12224         preg = getFreePtr(ic,&aop,FALSE);
12225         pic16_emitcode("mov","%s,%s",
12226                 preg->name,
12227                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12228         rname = preg->name ;
12229     } else
12230         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12231     
12232     pic16_freeAsmop(result,NULL,ic,TRUE);
12233     pic16_aopOp (right,ic,FALSE);
12234
12235     /* if bitfield then unpack the bits */
12236     if (IS_BITFIELD(retype)) 
12237         genPackBits (retype,result,right,rname,PPOINTER);
12238     else {
12239         /* we have can just get the values */
12240         int size = AOP_SIZE(right);
12241         int offset = 0 ;        
12242         
12243         while (size--) {
12244             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12245             
12246             MOVA(l);
12247             pic16_emitcode("movx","@%s,a",rname);
12248
12249             if (size)
12250                 pic16_emitcode("inc","%s",rname);
12251
12252             offset++;
12253         }
12254     }
12255     
12256     /* now some housekeeping stuff */
12257     if (aop) {
12258         /* we had to allocate for this iCode */
12259         pic16_freeAsmop(NULL,aop,ic,TRUE);
12260     } else { 
12261         /* we did not allocate which means left
12262            already in a pointer register, then
12263            if size > 0 && this could be used again
12264            we have to point it back to where it 
12265            belongs */
12266         if (AOP_SIZE(right) > 1 &&
12267             !OP_SYMBOL(result)->remat &&
12268             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12269               ic->depth )) {
12270             int size = AOP_SIZE(right) - 1;
12271             while (size--)
12272                 pic16_emitcode("dec","%s",rname);
12273         }
12274     }
12275
12276     /* done */
12277     pic16_freeAsmop(right,NULL,ic,TRUE);
12278     
12279         
12280 }
12281
12282 /*-----------------------------------------------------------------*/
12283 /* genFarPointerSet - set value from far space                     */
12284 /*-----------------------------------------------------------------*/
12285 static void genFarPointerSet (operand *right,
12286                               operand *result, iCode *ic)
12287 {
12288     int size, offset ;
12289     sym_link *retype = getSpec(operandType(right));
12290
12291     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12292     pic16_aopOp(result,ic,FALSE);
12293
12294     /* if the operand is already in dptr 
12295     then we do nothing else we move the value to dptr */
12296     if (AOP_TYPE(result) != AOP_STR) {
12297         /* if this is remateriazable */
12298         if (AOP_TYPE(result) == AOP_IMMD)
12299             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12300         else { /* we need to get it byte by byte */
12301             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12302             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12303             if (options.model == MODEL_FLAT24)
12304             {
12305                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12306             }
12307         }
12308     }
12309     /* so dptr know contains the address */
12310     pic16_freeAsmop(result,NULL,ic,TRUE);
12311     pic16_aopOp(right,ic,FALSE);
12312
12313     /* if bit then unpack */
12314     if (IS_BITFIELD(retype)) 
12315         genPackBits(retype,result,right,"dptr",FPOINTER);
12316     else {
12317         size = AOP_SIZE(right);
12318         offset = 0 ;
12319
12320         while (size--) {
12321             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12322             MOVA(l);
12323             pic16_emitcode("movx","@dptr,a");
12324             if (size)
12325                 pic16_emitcode("inc","dptr");
12326         }
12327     }
12328
12329     pic16_freeAsmop(right,NULL,ic,TRUE);
12330 }
12331
12332 /*-----------------------------------------------------------------*/
12333 /* genGenPointerSet - set value from generic pointer space         */
12334 /*-----------------------------------------------------------------*/
12335 #if 0
12336 static void genGenPointerSet (operand *right,
12337                               operand *result, iCode *ic)
12338 {
12339         int i, size, offset, lit;
12340         sym_link *retype = getSpec(operandType(right));
12341
12342         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12343
12344         pic16_aopOp(result,ic,FALSE);
12345         pic16_aopOp(right,ic,FALSE);
12346         size = AOP_SIZE(right);
12347         offset = 0;
12348
12349         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12350
12351         /* if the operand is already in dptr 
12352                 then we do nothing else we move the value to dptr */
12353         if (AOP_TYPE(result) != AOP_STR) {
12354                 /* if this is remateriazable */
12355                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12356                 // WARNING: anythig until "else" is untested!
12357                 if (AOP_TYPE(result) == AOP_IMMD) {
12358                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12359                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12360                         // load FSR0 from immediate
12361                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12362                         offset = 0;
12363                         while(size--) {
12364                                 if(size) {
12365                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12366                                 } else {
12367                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12368                                 }
12369                                 offset++;
12370                         }
12371                         goto release;
12372                 }
12373                 else { /* we need to get it byte by byte */
12374                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12375                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12376
12377                         // set up FSR0 with address of result
12378                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12379                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12380
12381                         /* hack hack! see if this the FSR. If so don't load W */
12382                         if(AOP_TYPE(right) != AOP_ACC) {
12383
12384                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12385
12386                                 if(AOP_TYPE(right) == AOP_LIT)
12387                                 {
12388                                         // copy literal
12389                                         // note: pic16_popGet handles sign extension
12390                                         for(i=0;i<size;i++) {
12391                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12392                                                 if(i < size-1)
12393                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12394                                                 else
12395                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12396                                         }
12397                                 } else {
12398                                         // copy regs
12399
12400                                         for(i=0;i<size;i++) {
12401                                                 if(i < size-1)
12402                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12403                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12404                                                 else
12405                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12406                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12407                                         }
12408                                 }
12409                                 goto release;
12410                         } 
12411                         // right = ACC
12412                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12413                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12414                         goto release;
12415         } // if (AOP_TYPE(result) != AOP_IMMD)
12416
12417         } // if (AOP_TYPE(result) != AOP_STR)
12418         /* so dptr know contains the address */
12419
12420
12421         /* if bit then unpack */
12422         if (IS_BITFIELD(retype)) 
12423                 genPackBits(retype,result,right,"dptr",GPOINTER);
12424         else {
12425                 size = AOP_SIZE(right);
12426                 offset = 0 ;
12427
12428                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12429
12430                 // set up FSR0 with address of result
12431                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12432                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12433         
12434                 while (size--) {
12435                         if (AOP_TYPE(right) == AOP_LIT) {
12436                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12437                                 if (size) {
12438                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12439                                 } else {
12440                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12441                                 }
12442                         } else { // no literal
12443                                 if(size) {
12444                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12445                                 } else {
12446                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12447                                 }
12448                         }
12449                         offset++;
12450                 }
12451         }
12452
12453         release:
12454         pic16_freeAsmop(right,NULL,ic,TRUE);
12455         pic16_freeAsmop(result,NULL,ic,TRUE);
12456 }
12457 #endif
12458
12459 static void genGenPointerSet (operand *right,
12460                               operand *result, iCode *ic)
12461 {
12462   int size;
12463   sym_link *retype = getSpec(operandType(right));
12464   char fgptrput[32];
12465
12466     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12467
12468     pic16_aopOp(result,ic,FALSE);
12469     pic16_aopOp(right,ic,FALSE);
12470     size = AOP_SIZE(right);
12471
12472     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12473
12474
12475     /* if bit then unpack */
12476     if (IS_BITFIELD(retype)) {
12477 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12478       genPackBits(retype,result,right,"dptr",GPOINTER);
12479       goto release;
12480     }
12481
12482     size = AOP_SIZE(right);
12483
12484     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12485
12486
12487
12488     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12489
12490     /* value of right+0 is placed on stack, which will be retrieved
12491      * by the support function this restoring the stack. The important
12492      * thing is that there is no need to manually restore stack pointer
12493      * here */
12494     pushaop(AOP(right), 0);
12495 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12496     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12497     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12498     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12499     
12500     /* load address to write to in WREG:FSR0H:FSR0L */
12501     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12502                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12503     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12504                                 pic16_popCopyReg(&pic16_pc_prodl)));
12505     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12506     
12507
12508     /* put code here */
12509     switch (size) {
12510       case 1: strcpy(fgptrput, "__gptrput1"); break;
12511       case 2: strcpy(fgptrput, "__gptrput2"); break;
12512       case 3: strcpy(fgptrput, "__gptrput3"); break;
12513       case 4: strcpy(fgptrput, "__gptrput4"); break;
12514       default:
12515         werror(W_POSSBUG2, __FILE__, __LINE__);
12516         abort();
12517     }
12518     
12519     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12520     
12521     {
12522       symbol *sym;
12523                   
12524         sym = newSymbol( fgptrput, 0 );
12525         sym->used++;
12526         strcpy(sym->rname, fgptrput);
12527         checkAddSym(&externs, sym);
12528     }
12529
12530 release:
12531     pic16_freeAsmop(right,NULL,ic,TRUE);
12532     pic16_freeAsmop(result,NULL,ic,TRUE);
12533 }
12534
12535 /*-----------------------------------------------------------------*/
12536 /* genPointerSet - stores the value into a pointer location        */
12537 /*-----------------------------------------------------------------*/
12538 static void genPointerSet (iCode *ic)
12539 {    
12540   operand *right, *result ;
12541   sym_link *type, *etype;
12542   int p_type;
12543
12544     FENTRY;
12545
12546     right = IC_RIGHT(ic);
12547     result = IC_RESULT(ic) ;
12548
12549     /* depending on the type of pointer we need to
12550     move it to the correct pointer register */
12551     type = operandType(result);
12552     etype = getSpec(type);
12553     /* if left is of type of pointer then it is simple */
12554     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12555         p_type = DCL_TYPE(type);
12556     }
12557     else {
12558         /* we have to go by the storage class */
12559         p_type = PTR_TYPE(SPEC_OCLS(etype));
12560
12561 /*      if (SPEC_OCLS(etype)->codesp ) { */
12562 /*          p_type = CPOINTER ;  */
12563 /*      } */
12564 /*      else */
12565 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12566 /*              p_type = FPOINTER ; */
12567 /*          else */
12568 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12569 /*                  p_type = PPOINTER ; */
12570 /*              else */
12571 /*                  if (SPEC_OCLS(etype) == idata ) */
12572 /*                      p_type = IPOINTER ; */
12573 /*                  else */
12574 /*                      p_type = POINTER ; */
12575     }
12576
12577     /* now that we have the pointer type we assign
12578     the pointer values */
12579     switch (p_type) {
12580       case POINTER:
12581       case IPOINTER:
12582         genNearPointerSet (right,result,ic);
12583         break;
12584
12585       case PPOINTER:
12586         genPagedPointerSet (right,result,ic);
12587         break;
12588
12589       case FPOINTER:
12590         genFarPointerSet (right,result,ic);
12591         break;
12592         
12593       case GPOINTER:
12594         genGenPointerSet (right,result,ic);
12595         break;
12596
12597       default:
12598         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12599           "genPointerSet: illegal pointer type");
12600     }
12601 }
12602
12603 /*-----------------------------------------------------------------*/
12604 /* genIfx - generate code for Ifx statement                        */
12605 /*-----------------------------------------------------------------*/
12606 static void genIfx (iCode *ic, iCode *popIc)
12607 {
12608   operand *cond = IC_COND(ic);
12609   int isbit =0;
12610
12611     FENTRY;
12612
12613     pic16_aopOp(cond,ic,FALSE);
12614
12615     /* get the value into acc */
12616     if (AOP_TYPE(cond) != AOP_CRY)
12617       pic16_toBoolean(cond);
12618     else
12619       isbit = 1;
12620     /* the result is now in the accumulator */
12621     pic16_freeAsmop(cond,NULL,ic,TRUE);
12622
12623     /* if there was something to be popped then do it */
12624     if (popIc)
12625       genIpop(popIc);
12626
12627     /* if the condition is  a bit variable */
12628     if (isbit && IS_ITEMP(cond) && 
12629         SPIL_LOC(cond)) {
12630       genIfxJump(ic,"c");
12631       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12632     } else {
12633       if (isbit && !IS_ITEMP(cond))
12634         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12635         else
12636         genIfxJump(ic,"a");
12637     }
12638     ic->generated = 1;
12639 }
12640
12641 /*-----------------------------------------------------------------*/
12642 /* genAddrOf - generates code for address of                       */
12643 /*-----------------------------------------------------------------*/
12644 static void genAddrOf (iCode *ic)
12645 {
12646   operand *result, *left;
12647   int size;
12648   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12649   pCodeOp *pcop0, *pcop1, *pcop2;
12650
12651     FENTRY;
12652
12653     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12654
12655     sym = OP_SYMBOL( IC_LEFT(ic) );
12656     
12657     if(sym->onStack) {
12658       /* get address of symbol on stack */
12659       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12660 #if 0
12661       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12662                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12663 #endif
12664
12665       // operands on stack are accessible via "FSR2 + index" with index
12666       // starting at 2 for arguments and growing from 0 downwards for
12667       // local variables (index == 0 is not assigned so we add one here)
12668       {
12669         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12670         if (soffs <= 0) {
12671           assert (soffs < 0);
12672           soffs++;
12673         } // if
12674         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12675         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12676         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12677         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12678         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12679         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12680         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12681       }
12682
12683       goto release;
12684     }
12685         
12686 //      if(pic16_debug_verbose) {
12687 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12688 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12689 //      }
12690         
12691     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12692     size = AOP_SIZE(IC_RESULT(ic));
12693
12694     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12695     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12696     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12697         
12698     if (size == 3) {
12699       pic16_emitpcode(POC_MOVLW, pcop0);
12700       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12701       pic16_emitpcode(POC_MOVLW, pcop1);
12702       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12703       pic16_emitpcode(POC_MOVLW, pcop2);
12704       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12705     } else
12706     if (size == 2) {
12707       pic16_emitpcode(POC_MOVLW, pcop0);
12708       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12709       pic16_emitpcode(POC_MOVLW, pcop1);
12710     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12711     } else {
12712       pic16_emitpcode(POC_MOVLW, pcop0);
12713       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12714     }
12715
12716     pic16_freeAsmop(left, NULL, ic, FALSE);
12717 release:
12718     pic16_freeAsmop(result,NULL,ic,TRUE);
12719 }
12720
12721
12722 #if 0
12723 /*-----------------------------------------------------------------*/
12724 /* genFarFarAssign - assignment when both are in far space         */
12725 /*-----------------------------------------------------------------*/
12726 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12727 {
12728     int size = AOP_SIZE(right);
12729     int offset = 0;
12730     char *l ;
12731     /* first push the right side on to the stack */
12732     while (size--) {
12733         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12734         MOVA(l);
12735         pic16_emitcode ("push","acc");
12736     }
12737     
12738     pic16_freeAsmop(right,NULL,ic,FALSE);
12739     /* now assign DPTR to result */
12740     pic16_aopOp(result,ic,FALSE);
12741     size = AOP_SIZE(result);
12742     while (size--) {
12743         pic16_emitcode ("pop","acc");
12744         pic16_aopPut(AOP(result),"a",--offset);
12745     }
12746     pic16_freeAsmop(result,NULL,ic,FALSE);
12747         
12748 }
12749 #endif
12750
12751 /*-----------------------------------------------------------------*/
12752 /* genAssign - generate code for assignment                        */
12753 /*-----------------------------------------------------------------*/
12754 static void genAssign (iCode *ic)
12755 {
12756   operand *result, *right;
12757   int size, offset,know_W;
12758   unsigned long lit = 0L;
12759
12760   result = IC_RESULT(ic);
12761   right  = IC_RIGHT(ic) ;
12762
12763   FENTRY;
12764   
12765   /* if they are the same */
12766   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12767     return ;
12768
12769   /* reversed order operands are aopOp'ed so that result operand
12770    * is effective in case right is a stack symbol. This maneauver
12771    * allows to use the _G.resDirect flag later */
12772   pic16_aopOp(result,ic,TRUE);
12773   pic16_aopOp(right,ic,FALSE);
12774
12775   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12776
12777   /* if they are the same registers */
12778   if (pic16_sameRegs(AOP(right),AOP(result)))
12779     goto release;
12780
12781   /* if the result is a bit */
12782   if (AOP_TYPE(result) == AOP_CRY) {
12783     /* if the right size is a literal then
12784        we know what the value is */
12785     if (AOP_TYPE(right) == AOP_LIT) {
12786           
12787       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12788                   pic16_popGet(AOP(result),0));
12789
12790       if (((int) operandLitValue(right))) 
12791         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12792                        AOP(result)->aopu.aop_dir,
12793                        AOP(result)->aopu.aop_dir);
12794       else
12795         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12796                        AOP(result)->aopu.aop_dir,
12797                        AOP(result)->aopu.aop_dir);
12798       goto release;
12799     }
12800
12801     /* the right is also a bit variable */
12802     if (AOP_TYPE(right) == AOP_CRY) {
12803       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12804       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12805       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12806
12807       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12808                      AOP(result)->aopu.aop_dir,
12809                      AOP(result)->aopu.aop_dir);
12810       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12811                      AOP(right)->aopu.aop_dir,
12812                      AOP(right)->aopu.aop_dir);
12813       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12814                      AOP(result)->aopu.aop_dir,
12815                      AOP(result)->aopu.aop_dir);
12816       goto release ;
12817     }
12818
12819     /* we need to or */
12820     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12821     pic16_toBoolean(right);
12822     emitSKPZ;
12823     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12824     //pic16_aopPut(AOP(result),"a",0);
12825     goto release ;
12826   }
12827
12828   /* bit variables done */
12829   /* general case */
12830   size = AOP_SIZE(result);
12831   offset = 0 ;
12832
12833   if(AOP_TYPE(right) == AOP_LIT) {
12834         if(!IS_FLOAT(operandType( right )))
12835                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12836         else {
12837            union {
12838               unsigned long lit_int;
12839               float lit_float;
12840             } info;
12841         
12842                 /* take care if literal is a float */
12843                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12844                 lit = info.lit_int;
12845         }
12846   }
12847
12848 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12849 //                      sizeof(unsigned long int), sizeof(float));
12850
12851
12852   if (AOP_TYPE(right) == AOP_REG) {
12853     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12854     while (size--) {
12855       
12856       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12857     } // while
12858     goto release;
12859   }
12860
12861   if(AOP_TYPE(right) != AOP_LIT
12862         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12863         && !IS_FUNC(OP_SYM_TYPE(right))
12864         ) {
12865         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12866         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12867
12868         // set up table pointer
12869         if(is_LitOp(right)) {
12870 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12871                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12872                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12873                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12874                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12875                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12876                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12877         } else {
12878 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12879                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12880                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12881                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12882                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12883                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12884                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12885         }
12886
12887         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12888         while(size--) {
12889                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12890                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12891                         pic16_popGet(AOP(result),offset)));
12892                 offset++;
12893         }
12894
12895         size = getSize(OP_SYM_ETYPE(right));
12896         if(AOP_SIZE(result) > size) {
12897                 size = AOP_SIZE(result) - size;
12898                 while(size--) {
12899                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12900                         offset++;
12901                 }
12902         }
12903         goto release;
12904   }
12905
12906
12907
12908 #if 0
12909 /* VR - What is this?! */
12910   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12911     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12912     if(aopIdx(AOP(result),0) == 4) {
12913
12914       /* this is a workaround to save value of right into wreg too,
12915        * value of wreg is going to be used later */
12916       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12917       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12919       goto release;
12920     } else
12921 //      assert(0);
12922       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12923   }
12924 #endif
12925
12926   know_W=-1;
12927   while (size--) {
12928   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12929     if(AOP_TYPE(right) == AOP_LIT) {
12930       if(lit&0xff) {
12931         if(know_W != (lit&0xff))
12932           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12933         know_W = lit&0xff;
12934         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12935       } else
12936         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12937
12938       lit >>= 8;
12939
12940     } else if (AOP_TYPE(right) == AOP_CRY) {
12941       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12942       if(offset == 0) {
12943         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12944         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12945         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12946       }
12947     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12948         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12949         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12950     } else {
12951       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12952
12953       if(!_G.resDirect)         /* use this aopForSym feature */
12954         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12955     }
12956             
12957     offset++;
12958   }
12959   
12960  release:
12961   pic16_freeAsmop (right,NULL,ic,FALSE);
12962   pic16_freeAsmop (result,NULL,ic,TRUE);
12963 }   
12964
12965 /*-----------------------------------------------------------------*/
12966 /* genJumpTab - generates code for jump table                       */
12967 /*-----------------------------------------------------------------*/
12968 static void genJumpTab (iCode *ic)
12969 {
12970   symbol *jtab;
12971   char *l;
12972   pCodeOp *jt_offs;
12973   pCodeOp *jt_offs_hi;
12974   pCodeOp *jt_label;
12975
12976     FENTRY;
12977
12978     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12979     /* get the condition into accumulator */
12980     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12981     MOVA(l);
12982     /* multiply by three */
12983     pic16_emitcode("add","a,acc");
12984     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12985
12986     jtab = newiTempLabel(NULL);
12987     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12988     pic16_emitcode("jmp","@a+dptr");
12989     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12990
12991 #if 0
12992     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12993     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12994     emitSKPNC;
12995     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12996     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12997     pic16_emitpLabel(jtab->key);
12998
12999 #else
13000
13001     jt_offs = pic16_popGetTempReg(0);
13002     jt_offs_hi = pic16_popGetTempReg(1);
13003     jt_label = pic16_popGetLabel (jtab->key);
13004     //fprintf (stderr, "Creating jump table...\n");
13005
13006     // calculate offset into jump table (idx * sizeof (GOTO))
13007     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
13008     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13009     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13010     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13011     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13012     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13013     pic16_emitpcode(POC_MOVWF , jt_offs);
13014
13015     // prepare PCLATx (set to first entry in jump table)
13016     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13017     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13018     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13019     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13020     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13021
13022     // set PCLATx to selected entry (new PCL is stored in jt_offs)
13023     pic16_emitpcode(POC_ADDWF , jt_offs);
13024     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13025     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13026     emitSKPNC;
13027     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
13028
13029     // release temporaries and prepare jump into table (new PCL --> WREG)
13030     pic16_emitpcode(POC_MOVFW , jt_offs);
13031     pic16_popReleaseTempReg (jt_offs_hi, 1);
13032     pic16_popReleaseTempReg (jt_offs, 0);
13033
13034     // jump into the table
13035     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13036
13037     pic16_emitpLabelFORCE(jtab->key);
13038
13039 #endif
13040     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13041
13042     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13043     /* now generate the jump labels */
13044     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13045          jtab = setNextItem(IC_JTLABELS(ic))) {
13046 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13047         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13048         
13049     }
13050     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13051
13052 }
13053
13054 /*-----------------------------------------------------------------*/
13055 /* genMixedOperation - gen code for operators between mixed types  */
13056 /*-----------------------------------------------------------------*/
13057 /*
13058   TSD - Written for the PIC port - but this unfortunately is buggy.
13059   This routine is good in that it is able to efficiently promote 
13060   types to different (larger) sizes. Unfortunately, the temporary
13061   variables that are optimized out by this routine are sometimes
13062   used in other places. So until I know how to really parse the 
13063   iCode tree, I'm going to not be using this routine :(.
13064 */
13065 static int genMixedOperation (iCode *ic)
13066 {
13067 #if 0
13068   operand *result = IC_RESULT(ic);
13069   sym_link *ctype = operandType(IC_LEFT(ic));
13070   operand *right = IC_RIGHT(ic);
13071   int ret = 0;
13072   int big,small;
13073   int offset;
13074
13075   iCode *nextic;
13076   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13077
13078   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13079
13080   nextic = ic->next;
13081   if(!nextic)
13082     return 0;
13083
13084   nextright = IC_RIGHT(nextic);
13085   nextleft  = IC_LEFT(nextic);
13086   nextresult = IC_RESULT(nextic);
13087
13088   pic16_aopOp(right,ic,FALSE);
13089   pic16_aopOp(result,ic,FALSE);
13090   pic16_aopOp(nextright,  nextic, FALSE);
13091   pic16_aopOp(nextleft,   nextic, FALSE);
13092   pic16_aopOp(nextresult, nextic, FALSE);
13093
13094   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13095
13096     operand *t = right;
13097     right = nextright;
13098     nextright = t; 
13099
13100     pic16_emitcode(";remove right +","");
13101
13102   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13103 /*
13104     operand *t = right;
13105     right = nextleft;
13106     nextleft = t; 
13107 */
13108     pic16_emitcode(";remove left +","");
13109   } else
13110     return 0;
13111
13112   big = AOP_SIZE(nextleft);
13113   small = AOP_SIZE(nextright);
13114
13115   switch(nextic->op) {
13116
13117   case '+':
13118     pic16_emitcode(";optimize a +","");
13119     /* if unsigned or not an integral type */
13120     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13121       pic16_emitcode(";add a bit to something","");
13122     } else {
13123
13124       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13125
13126       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13127         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13128         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13129       } else
13130         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13131
13132       offset = 0;
13133       while(--big) {
13134
13135         offset++;
13136
13137         if(--small) {
13138           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13139             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13140             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13141           }
13142
13143           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13144           emitSKPNC;
13145           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13146                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13147                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13148           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13149           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13150
13151         } else {
13152           pic16_emitcode("rlf","known_zero,w");
13153
13154           /*
13155             if right is signed
13156               btfsc  right,7
13157                addlw ff
13158           */
13159           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13160             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13161             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13162           } else {
13163             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13164           }
13165         }
13166       }
13167       ret = 1;
13168     }
13169   }
13170   ret = 1;
13171
13172 release:
13173   pic16_freeAsmop(right,NULL,ic,TRUE);
13174   pic16_freeAsmop(result,NULL,ic,TRUE);
13175   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13176   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13177   if(ret)
13178     nextic->generated = 1;
13179
13180   return ret;
13181 #else
13182   return 0;
13183 #endif
13184 }
13185 /*-----------------------------------------------------------------*/
13186 /* genCast - gen code for casting                                  */
13187 /*-----------------------------------------------------------------*/
13188 static void genCast (iCode *ic)
13189 {
13190   operand *result = IC_RESULT(ic);
13191   sym_link *ctype = operandType(IC_LEFT(ic));
13192   sym_link *rtype = operandType(IC_RIGHT(ic));
13193   sym_link *restype = operandType(IC_RESULT(ic));
13194   operand *right = IC_RIGHT(ic);
13195   int size, offset ;
13196
13197
13198     FENTRY;
13199
13200         /* if they are equivalent then do nothing */
13201 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13202 //              return ;
13203
13204         pic16_aopOp(right,ic,FALSE) ;
13205         pic16_aopOp(result,ic,FALSE);
13206
13207         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13208
13209
13210         /* if the result is a bit */
13211         if (AOP_TYPE(result) == AOP_CRY) {
13212         
13213                 /* if the right size is a literal then
13214                  * we know what the value is */
13215                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13216
13217                 if (AOP_TYPE(right) == AOP_LIT) {
13218                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13219                                 pic16_popGet(AOP(result),0));
13220
13221                         if (((int) operandLitValue(right))) 
13222                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13223                                         AOP(result)->aopu.aop_dir,
13224                                         AOP(result)->aopu.aop_dir);
13225                         else
13226                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13227                                         AOP(result)->aopu.aop_dir,
13228                                         AOP(result)->aopu.aop_dir);
13229                         goto release;
13230                 }
13231
13232                 /* the right is also a bit variable */
13233                 if (AOP_TYPE(right) == AOP_CRY) {
13234                         emitCLRC;
13235                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13236
13237                         pic16_emitcode("clrc","");
13238                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13239                                 AOP(right)->aopu.aop_dir,
13240                                 AOP(right)->aopu.aop_dir);
13241                         pic16_aopPut(AOP(result),"c",0);
13242                         goto release ;
13243                 }
13244
13245                 /* we need to or */
13246                 if (AOP_TYPE(right) == AOP_REG) {
13247                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13248                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13249                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13250                 }
13251                 pic16_toBoolean(right);
13252                 pic16_aopPut(AOP(result),"a",0);
13253                 goto release ;
13254         }
13255
13256         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13257           int offset = 1;
13258
13259                 size = AOP_SIZE(result);
13260
13261                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13262
13263                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13264                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13265                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13266
13267                 while (size--)
13268                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13269
13270                 goto release;
13271         }
13272
13273         if(IS_BITFIELD(getSpec(restype))
13274           && IS_BITFIELD(getSpec(rtype))) {
13275           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13276         }
13277
13278         /* if they are the same size : or less */
13279         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13280
13281                 /* if they are in the same place */
13282                 if (pic16_sameRegs(AOP(right),AOP(result)))
13283                         goto release;
13284
13285                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13286 #if 0
13287                 if (IS_PTR_CONST(rtype))
13288 #else
13289                 if (IS_CODEPTR(rtype))
13290 #endif
13291                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13292
13293 #if 0
13294                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13295 #else
13296                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13297 #endif
13298                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13299
13300 #if 0
13301                 if(AOP_TYPE(right) == AOP_IMMD) {
13302                   pCodeOp *pcop0, *pcop1, *pcop2;
13303                   symbol *sym = OP_SYMBOL( right );
13304
13305                         size = AOP_SIZE(result);
13306                         /* low */
13307                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13308                         /* high */
13309                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13310                         /* upper */
13311                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13312         
13313                         if (size == 3) {
13314                                 pic16_emitpcode(POC_MOVLW, pcop0);
13315                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13316                                 pic16_emitpcode(POC_MOVLW, pcop1);
13317                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13318                                 pic16_emitpcode(POC_MOVLW, pcop2);
13319                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13320                         } else
13321                         if (size == 2) {
13322                                 pic16_emitpcode(POC_MOVLW, pcop0);
13323                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13324                                 pic16_emitpcode(POC_MOVLW, pcop1);
13325                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13326                         } else {
13327                                 pic16_emitpcode(POC_MOVLW, pcop0);
13328                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13329                         }
13330                 } else
13331 #endif
13332                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13333                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13334                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13335                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13336                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13337                         if(AOP_SIZE(result) <2)
13338                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13339                 } else {
13340                         /* if they in different places then copy */
13341                         size = AOP_SIZE(result);
13342                         offset = 0 ;
13343                         while (size--) {
13344                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13345                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13346                                 offset++;
13347                         }
13348                 }
13349                 goto release;
13350         }
13351
13352         /* if the result is of type pointer */
13353         if (IS_PTR(ctype)) {
13354           int p_type;
13355           sym_link *type = operandType(right);
13356           sym_link *etype = getSpec(type);
13357
13358                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13359
13360                 /* pointer to generic pointer */
13361                 if (IS_GENPTR(ctype)) {
13362                   char *l = zero;
13363             
13364                         if (IS_PTR(type)) 
13365                                 p_type = DCL_TYPE(type);
13366                         else {
13367                 /* we have to go by the storage class */
13368                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13369
13370 /*              if (SPEC_OCLS(etype)->codesp )  */
13371 /*                  p_type = CPOINTER ;  */
13372 /*              else */
13373 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13374 /*                      p_type = FPOINTER ; */
13375 /*                  else */
13376 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13377 /*                          p_type = PPOINTER; */
13378 /*                      else */
13379 /*                          if (SPEC_OCLS(etype) == idata ) */
13380 /*                              p_type = IPOINTER ; */
13381 /*                          else */
13382 /*                              p_type = POINTER ; */
13383             }
13384                 
13385             /* the first two bytes are known */
13386       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13387             size = GPTRSIZE - 1; 
13388             offset = 0 ;
13389             while (size--) {
13390               if(offset < AOP_SIZE(right)) {
13391                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13392                 mov2f(AOP(result), AOP(right), offset);
13393 /*
13394                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13395                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13396                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13397                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13398                 } else { 
13399                   
13400                   pic16_aopPut(AOP(result),
13401                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13402                          offset);
13403                 }
13404 */
13405               } else 
13406                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13407               offset++;
13408             }
13409             /* the last byte depending on type */
13410             switch (p_type) {
13411             case IPOINTER:
13412             case POINTER:
13413                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13414                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13415 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13416                 break;
13417
13418             case CPOINTER:
13419                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13420                 break;
13421
13422             case FPOINTER:
13423               pic16_emitcode(";BUG!? ","%d",__LINE__);
13424                 l = one;
13425                 break;
13426             case PPOINTER:
13427               pic16_emitcode(";BUG!? ","%d",__LINE__);
13428                 l = "#0x03";
13429                 break;
13430
13431             case GPOINTER:
13432                 if (GPTRSIZE > AOP_SIZE(right)) {
13433                   // assume data pointer... THIS MIGHT BE WRONG!
13434                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13435                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13436                 } else {
13437                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13438                 }
13439               break;
13440               
13441             default:
13442                 /* this should never happen */
13443                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13444                        "got unknown pointer type");
13445                 exit(1);
13446             }
13447             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13448             goto release ;
13449         }
13450         
13451         /* just copy the pointers */
13452         size = AOP_SIZE(result);
13453         offset = 0 ;
13454         while (size--) {
13455             pic16_aopPut(AOP(result),
13456                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13457                    offset);
13458             offset++;
13459         }
13460         goto release ;
13461     }
13462     
13463
13464
13465     /* so we now know that the size of destination is greater
13466     than the size of the source.
13467     Now, if the next iCode is an operator then we might be
13468     able to optimize the operation without performing a cast.
13469     */
13470     if(genMixedOperation(ic))
13471       goto release;
13472
13473     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13474     
13475     /* we move to result for the size of source */
13476     size = AOP_SIZE(right);
13477     offset = 0 ;
13478     while (size--) {
13479       mov2f(AOP(result), AOP(right), offset);
13480       offset++;
13481     }
13482
13483     /* now depending on the sign of the destination */
13484     size = AOP_SIZE(result) - AOP_SIZE(right);
13485     /* if unsigned or not an integral type */
13486     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13487       while (size--)
13488         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13489     } else {
13490       /* we need to extend the sign :( */
13491
13492       if(size == 1) {
13493         /* Save one instruction of casting char to int */
13494         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13495         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13496         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13497       } else {
13498         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13499
13500         if(offset)
13501           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13502         else
13503           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13504         
13505         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13506
13507         while (size--)
13508           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13509       }
13510     }
13511
13512 release:
13513     pic16_freeAsmop(right,NULL,ic,TRUE);
13514     pic16_freeAsmop(result,NULL,ic,TRUE);
13515
13516 }
13517
13518 /*-----------------------------------------------------------------*/
13519 /* genDjnz - generate decrement & jump if not zero instrucion      */
13520 /*-----------------------------------------------------------------*/
13521 static int genDjnz (iCode *ic, iCode *ifx)
13522 {
13523     symbol *lbl, *lbl1;
13524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13525
13526     if (!ifx)
13527         return 0;
13528     
13529     /* if the if condition has a false label
13530        then we cannot save */
13531     if (IC_FALSE(ifx))
13532         return 0;
13533
13534     /* if the minus is not of the form 
13535        a = a - 1 */
13536     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13537         !IS_OP_LITERAL(IC_RIGHT(ic)))
13538         return 0;
13539
13540     if (operandLitValue(IC_RIGHT(ic)) != 1)
13541         return 0;
13542
13543     /* if the size of this greater than one then no
13544        saving */
13545     if (getSize(operandType(IC_RESULT(ic))) > 1)
13546         return 0;
13547
13548     /* otherwise we can save BIG */
13549     lbl = newiTempLabel(NULL);
13550     lbl1= newiTempLabel(NULL);
13551
13552     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13553     
13554     if (IS_AOP_PREG(IC_RESULT(ic))) {
13555         pic16_emitcode("dec","%s",
13556                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13557         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13558         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13559     } else {    
13560
13561
13562       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13563       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13564
13565       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13566       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13567
13568     }
13569     
13570     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13571     ifx->generated = 1;
13572     return 1;
13573 }
13574
13575 /*-----------------------------------------------------------------*/
13576 /* genReceive - generate code for a receive iCode                  */
13577 /*-----------------------------------------------------------------*/
13578 static void genReceive (iCode *ic)
13579 {    
13580
13581   FENTRY;
13582
13583 #if 0
13584   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13585         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13586 #endif
13587 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13588
13589   if (isOperandInFarSpace(IC_RESULT(ic))
13590       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13591           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13592
13593     int size = getSize(operandType(IC_RESULT(ic)));
13594     int offset =  pic16_fReturnSizePic - size;
13595
13596       assert( 0 );
13597       while (size--) {
13598         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13599                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13600                       offset++;
13601         }
13602
13603       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13604
13605       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13606       size = AOP_SIZE(IC_RESULT(ic));
13607       offset = 0;
13608       while (size--) {
13609         pic16_emitcode ("pop","acc");
13610         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13611       }
13612   } else {
13613     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13614     _G.accInUse++;
13615     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13616     _G.accInUse--;
13617
13618     /* set pseudo stack pointer to where it should be - dw*/
13619     GpsuedoStkPtr = ic->parmBytes;
13620
13621     /* setting GpsuedoStkPtr has side effects here: */
13622     assignResultValue(IC_RESULT(ic), 0);
13623   }
13624
13625   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13626 }
13627
13628 /*-----------------------------------------------------------------*/
13629 /* genDummyRead - generate code for dummy read of volatiles        */
13630 /*-----------------------------------------------------------------*/
13631 static void
13632 genDummyRead (iCode * ic)
13633 {
13634   operand *op;
13635   int i;
13636
13637   op = IC_RIGHT(ic);
13638   if (op && IS_SYMOP(op)) {
13639     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13640       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13641       return;
13642     }
13643     pic16_aopOp (op, ic, FALSE);
13644     for (i=0; i < AOP_SIZE(op); i++) {
13645       // may need to protect this from the peepholer -- this is not nice but works...
13646       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13647       pic16_mov2w (AOP(op),i);
13648       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13649     } // for i
13650     pic16_freeAsmop (op, NULL, ic, TRUE);
13651   } else if (op) {
13652     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13653   } // if
13654 }
13655
13656 /*-----------------------------------------------------------------*/
13657 /* genpic16Code - generate code for pic16 based controllers        */
13658 /*-----------------------------------------------------------------*/
13659 /*
13660  * At this point, ralloc.c has gone through the iCode and attempted
13661  * to optimize in a way suitable for a PIC. Now we've got to generate
13662  * PIC instructions that correspond to the iCode.
13663  *
13664  * Once the instructions are generated, we'll pass through both the
13665  * peep hole optimizer and the pCode optimizer.
13666  *-----------------------------------------------------------------*/
13667
13668 void genpic16Code (iCode *lic)
13669 {
13670   iCode *ic;
13671   int cln = 0;
13672
13673     lineHead = lineCurr = NULL;
13674
13675     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13676     pic16_addpBlock(pb);
13677
13678 #if 0
13679     /* if debug information required */
13680     if (options.debug && currFunc) {
13681       if (currFunc) {
13682         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13683       }
13684     }
13685 #endif
13686
13687     for (ic = lic ; ic ; ic = ic->next ) {
13688
13689       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13690       if ( cln != ic->lineno ) {
13691         if ( options.debug ) {
13692           debugFile->writeCLine (ic);
13693         }
13694         
13695         if(!options.noCcodeInAsm) {
13696           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13697               printCLine(ic->filename, ic->lineno)));
13698         }
13699
13700         cln = ic->lineno ;
13701       }
13702         
13703       if(options.iCodeInAsm) {
13704         char *l;
13705
13706           /* insert here code to print iCode as comment */
13707           l = Safe_strdup(printILine(ic));
13708           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13709       }
13710         
13711       /* if the result is marked as
13712        * spilt and rematerializable or code for
13713        * this has already been generated then
13714        * do nothing */
13715       if (resultRemat(ic) || ic->generated ) 
13716         continue ;
13717         
13718       /* depending on the operation */
13719       switch (ic->op) {
13720         case '!' :
13721           pic16_genNot(ic);
13722           break;
13723             
13724         case '~' :
13725           pic16_genCpl(ic);
13726           break;
13727             
13728         case UNARYMINUS:
13729           genUminus (ic);
13730           break;
13731             
13732         case IPUSH:
13733           genIpush (ic);
13734           break;
13735             
13736         case IPOP:
13737           /* IPOP happens only when trying to restore a 
13738            * spilt live range, if there is an ifx statement
13739            * following this pop then the if statement might
13740            * be using some of the registers being popped which
13741            * would destroy the contents of the register so
13742            * we need to check for this condition and handle it */
13743            if (ic->next
13744              && ic->next->op == IFX
13745              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13746                genIfx (ic->next,ic);
13747           else
13748             genIpop (ic);
13749           break; 
13750             
13751         case CALL:
13752           genCall (ic);
13753           break;
13754             
13755         case PCALL:
13756           genPcall (ic);
13757           break;
13758             
13759         case FUNCTION:
13760           genFunction (ic);
13761           break;
13762             
13763         case ENDFUNCTION:
13764           genEndFunction (ic);
13765           break;
13766             
13767         case RETURN:
13768           genRet (ic);
13769           break;
13770             
13771         case LABEL:
13772           genLabel (ic);
13773           break;
13774             
13775         case GOTO:
13776           genGoto (ic);
13777           break;
13778             
13779         case '+' :
13780           pic16_genPlus (ic) ;
13781           break;
13782             
13783         case '-' :
13784           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13785             pic16_genMinus (ic);
13786           break;
13787
13788         case '*' :
13789           genMult (ic);
13790           break;
13791             
13792         case '/' :
13793           genDiv (ic) ;
13794           break;
13795             
13796         case '%' :
13797           genMod (ic);
13798           break;
13799             
13800         case '>' :
13801           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13802           break;
13803             
13804         case '<' :
13805           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13806           break;
13807             
13808         case LE_OP:
13809         case GE_OP:
13810         case NE_OP:
13811           /* note these two are xlated by algebraic equivalence
13812            * during parsing SDCC.y */
13813           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13814             "got '>=' or '<=' shouldn't have come here");
13815           break;
13816
13817         case EQ_OP:
13818           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13819           break;            
13820             
13821         case AND_OP:
13822           genAndOp (ic);
13823           break;
13824             
13825         case OR_OP:
13826           genOrOp (ic);
13827           break;
13828             
13829         case '^' :
13830           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13831           break;
13832             
13833         case '|' :
13834           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13835           break;
13836             
13837         case BITWISEAND:
13838           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13839           break;
13840             
13841         case INLINEASM:
13842           genInline (ic);
13843           break;
13844             
13845         case RRC:
13846           genRRC (ic);
13847           break;
13848             
13849         case RLC:
13850           genRLC (ic);
13851           break;
13852             
13853         case GETHBIT:
13854           genGetHbit (ic);
13855           break;
13856             
13857         case LEFT_OP:
13858           genLeftShift (ic);
13859           break;
13860             
13861         case RIGHT_OP:
13862           genRightShift (ic);
13863           break;
13864             
13865         case GET_VALUE_AT_ADDRESS:
13866           genPointerGet(ic);
13867           break;
13868             
13869         case '=' :
13870           if (POINTER_SET(ic))
13871             genPointerSet(ic);
13872           else
13873             genAssign(ic);
13874           break;
13875             
13876         case IFX:
13877           genIfx (ic,NULL);
13878           break;
13879             
13880         case ADDRESS_OF:
13881           genAddrOf (ic);
13882           break;
13883             
13884         case JUMPTABLE:
13885           genJumpTab (ic);
13886           break;
13887             
13888         case CAST:
13889           genCast (ic);
13890           break;
13891             
13892         case RECEIVE:
13893           genReceive(ic);
13894           break;
13895             
13896         case SEND:
13897           addSet(&_G.sendSet,ic);
13898           break;
13899
13900         case DUMMY_READ_VOLATILE:
13901           genDummyRead (ic);
13902           break;
13903
13904         default :
13905           ic = ic;
13906       }
13907     }
13908
13909
13910     /* now we are ready to call the
13911        peep hole optimizer */
13912     if (!options.nopeep)
13913       peepHole (&lineHead);
13914
13915     /* now do the actual printing */
13916     printLine (lineHead, codeOutFile);
13917
13918 #ifdef PCODE_DEBUG
13919     DFPRINTF((stderr,"printing pBlock\n\n"));
13920     pic16_printpBlock(stdout,pb);
13921 #endif
13922
13923     return;
13924 }
13925