* device/include/pic16/string.h: modified prototype for memccpy()
[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         if(_G.accInUse) {
707                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
708         }
709         
710         for(i=0;i<aop->size;i++) {
711
712           /* initialise for stack access via frame pointer */
713           // operands on stack are accessible via "FSR2 + index" with index
714           // starting at 2 for arguments and growing from 0 downwards for
715           // local variables (index == 0 is not assigned so we add one here)
716           {
717             int soffs = sym->stack;
718             if (soffs <= 0) {
719               assert (soffs < 0);
720               soffs++;
721             } // if
722             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
723             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
724                             pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
725           }
726         }
727         
728         if(_G.accInUse) {
729                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730         }
731         
732         return (aop);
733 #endif
734
735 #if 0
736         /* now assign the address of the variable to 
737         the pointer register */
738         if (aop->type != AOP_STK) {
739
740             if (sym->onStack) {
741                     if ( _G.accInUse )
742                         pic16_emitcode("push","acc");
743
744                     pic16_emitcode("mov","a,_bp");
745                     pic16_emitcode("add","a,#0x%02x",
746                              ((sym->stack < 0) ?
747                               ((char)(sym->stack - _G.nRegsSaved )) :
748                               ((char)sym->stack)) & 0xff);
749                     pic16_emitcode("mov","%s,a",
750                              aop->aopu.aop_ptr->name);
751
752                     if ( _G.accInUse )
753                         pic16_emitcode("pop","acc");
754             } else
755                 pic16_emitcode("mov","%s,#%s",
756                          aop->aopu.aop_ptr->name,
757                          sym->rname);
758             aop->paged = space->paged;
759         } else
760             aop->aopu.aop_stk = sym->stack;
761         return aop;
762 #endif
763
764     }
765 #endif
766
767 #if 0
768     if (sym->onStack && options.stack10bit)
769     {
770         /* It's on the 10 bit stack, which is located in
771          * far data space.
772          */
773          
774       //DEBUGpic16_emitcode(";","%d",__LINE__);
775
776         if ( _G.accInUse )
777                 pic16_emitcode("push","acc");
778
779         pic16_emitcode("mov","a,_bp");
780         pic16_emitcode("add","a,#0x%02x",
781                  ((sym->stack < 0) ?
782                    ((char)(sym->stack - _G.nRegsSaved )) :
783                    ((char)sym->stack)) & 0xff);
784         
785         genSetDPTR(1);
786         pic16_emitcode ("mov","dpx1,#0x40");
787         pic16_emitcode ("mov","dph1,#0x00");
788         pic16_emitcode ("mov","dpl1, a");
789         genSetDPTR(0);
790         
791         if ( _G.accInUse )
792             pic16_emitcode("pop","acc");
793             
794         sym->aop = aop = newAsmop(AOP_DPTR2);
795         aop->size = getSize(sym->type); 
796         return aop;
797     }
798 #endif
799
800 #if 1
801     /* special case for a function */
802     if (IS_FUNC(sym->type)) {   
803         sym->aop = aop = newAsmop(AOP_PCODE);
804         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
805         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
806         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
807         PCOI(aop->aopu.pcop)->index = 0;
808         aop->size = FPTRSIZE; 
809         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
810         return aop;
811     }
812 #endif
813
814
815
816     //DEBUGpic16_emitcode(";","%d",__LINE__);
817     /* if in bit space */
818     if (IN_BITSPACE(space)) {
819         sym->aop = aop = newAsmop (AOP_CRY);
820         aop->aopu.aop_dir = sym->rname ;
821         aop->size = getSize(sym->type);
822         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
823         return aop;
824     }
825     /* if it is in direct space */
826     if (IN_DIRSPACE(space)) {
827         sym->aop = aop = newAsmop (AOP_DIR);
828         aop->aopu.aop_dir = sym->rname ;
829         aop->size = getSize(sym->type);
830         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
831         pic16_allocDirReg( IC_LEFT(ic) );
832         return aop;
833     }
834
835
836     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
837         sym->aop = aop = newAsmop (AOP_DIR);
838         aop->aopu.aop_dir = sym->rname ;
839         aop->size = getSize(sym->type);
840         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841         pic16_allocDirReg( IC_LEFT(ic) );
842         return aop;
843     }
844
845
846     /* only remaining is far space */
847     sym->aop = aop = newAsmop(AOP_PCODE);
848
849 /* change the next if to 1 to revert to good old immediate code */
850         if(IN_CODESPACE(space)) {
851                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
852                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
853                 PCOI(aop->aopu.pcop)->index = 0;
854         } else {
855                 /* try to allocate via direct register */
856                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
857 //              aop->size = getSize( sym->type );
858         }
859
860         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
861                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
862
863 #if 0
864         if(!pic16_allocDirReg (IC_LEFT(ic)))
865                 return NULL;
866 #endif
867
868         if(IN_DIRSPACE( space ))
869                 aop->size = PTRSIZE;
870         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
871                 aop->size = FPTRSIZE;
872         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
873         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
874         else if(sym->onStack) {
875                 aop->size = PTRSIZE;
876         } else {
877           if(SPEC_SCLS(sym->etype) == S_PDATA) {
878             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
879             aop->size = FPTRSIZE;
880           } else
881                 assert( 0 );
882         }
883
884     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
885
886     /* if it is in code space */
887     if (IN_CODESPACE(space))
888         aop->code = 1;
889
890     return aop;     
891 }
892
893 /*-----------------------------------------------------------------*/
894 /* aopForRemat - rematerialzes an object                           */
895 /*-----------------------------------------------------------------*/
896 static asmop *aopForRemat (operand *op) // x symbol *sym)
897 {
898   symbol *sym = OP_SYMBOL(op);
899   operand *refop;
900   iCode *ic = NULL, *oldic;
901   asmop *aop = newAsmop(AOP_PCODE);
902   int val = 0;
903   int offset = 0;
904   int viaimmd=0;
905
906     FENTRY2;
907     
908         ic = sym->rematiCode;
909
910         if(IS_OP_POINTER(op)) {
911                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
912         }
913
914         for (;;) {
915                 oldic = ic;
916
917 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
918         
919                 if (ic->op == '+') {
920                         val += (int) operandLitValue(IC_RIGHT(ic));
921                 } else if (ic->op == '-') {
922                         val -= (int) operandLitValue(IC_RIGHT(ic));
923                 } else
924                         break;
925                 
926                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
927         }
928
929         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
930         refop = IC_LEFT(ic);
931
932         if(!op->isaddr)viaimmd++; else viaimmd=0;
933                 
934 /* set the following if to 1 to revert to good old immediate code */
935         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
936                 || viaimmd) {
937
938                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
939
940                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
941
942 #if 0
943                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
944 #else
945                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
946 #endif
947
948                 PCOI(aop->aopu.pcop)->index = val;
949                 
950                 aop->size = getSize( sym->type );
951         } else {
952                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
953
954                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
955                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
956
957                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
958         }
959
960
961         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
962                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
963 #if 0
964                 val, IS_PTR_CONST(operandType(op)));
965 #else
966                 val, IS_CODEPTR(operandType(op)));
967 #endif
968
969 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
970
971         pic16_allocDirReg (IC_LEFT(ic));
972
973         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
974                 aop->code = 1;
975
976   return aop;        
977 }
978
979 #if 0
980 static int aopIdx (asmop *aop, int offset)
981 {
982   if(!aop)
983     return -1;
984
985   if(aop->type !=  AOP_REG)
986     return -2;
987         
988   return aop->aopu.aop_reg[offset]->rIdx;
989
990 }
991 #endif
992
993 /*-----------------------------------------------------------------*/
994 /* regsInCommon - two operands have some registers in common       */
995 /*-----------------------------------------------------------------*/
996 static bool regsInCommon (operand *op1, operand *op2)
997 {
998     symbol *sym1, *sym2;
999     int i;
1000
1001     /* if they have registers in common */
1002     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1003         return FALSE ;
1004
1005     sym1 = OP_SYMBOL(op1);
1006     sym2 = OP_SYMBOL(op2);
1007
1008     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1009         return FALSE ;
1010
1011     for (i = 0 ; i < sym1->nRegs ; i++) {
1012         int j;
1013         if (!sym1->regs[i])
1014             continue ;
1015
1016         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1017             if (!sym2->regs[j])
1018                 continue ;
1019
1020             if (sym2->regs[j] == sym1->regs[i])
1021                 return TRUE ;
1022         }
1023     }
1024
1025     return FALSE ;
1026 }
1027
1028 /*-----------------------------------------------------------------*/
1029 /* operandsEqu - equivalent                                        */
1030 /*-----------------------------------------------------------------*/
1031 static bool operandsEqu ( operand *op1, operand *op2)
1032 {
1033     symbol *sym1, *sym2;
1034
1035     /* if they not symbols */
1036     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1037         return FALSE;
1038
1039     sym1 = OP_SYMBOL(op1);
1040     sym2 = OP_SYMBOL(op2);
1041
1042     /* if both are itemps & one is spilt
1043        and the other is not then false */
1044     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1045         sym1->isspilt != sym2->isspilt )
1046         return FALSE ;
1047
1048     /* if they are the same */
1049     if (sym1 == sym2)
1050         return TRUE ;
1051
1052     if (sym1->rname[0] && sym2->rname[0]
1053         && strcmp (sym1->rname, sym2->rname) == 0)
1054         return TRUE;
1055
1056
1057     /* if left is a tmp & right is not */
1058     if (IS_ITEMP(op1)  && 
1059         !IS_ITEMP(op2) &&
1060         sym1->isspilt  &&
1061         (sym1->usl.spillLoc == sym2))
1062         return TRUE;
1063
1064     if (IS_ITEMP(op2)  && 
1065         !IS_ITEMP(op1) &&
1066         sym2->isspilt  &&
1067         sym1->level > 0 &&
1068         (sym2->usl.spillLoc == sym1))
1069         return TRUE ;
1070
1071     return FALSE ;
1072 }
1073
1074 /*-----------------------------------------------------------------*/
1075 /* pic16_sameRegs - two asmops have the same registers                   */
1076 /*-----------------------------------------------------------------*/
1077 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1078 {
1079     int i;
1080
1081     if (aop1 == aop2)
1082         return TRUE ;
1083
1084     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1085                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1086
1087     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1088
1089     if (aop1->type != AOP_REG ||
1090         aop2->type != AOP_REG )
1091         return FALSE ;
1092
1093     /* This is a bit too restrictive if one is a subset of the other...
1094     if (aop1->size != aop2->size )
1095         return FALSE ;
1096     */
1097
1098     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1099 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1100
1101 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1102         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1103             return FALSE ;
1104     }
1105
1106     return TRUE ;
1107 }
1108
1109 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1110 {
1111     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1112                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1113
1114     if(aop1 == aop2)return TRUE;
1115     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1116       
1117       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1118     
1119   return TRUE;
1120 }
1121
1122
1123 /*-----------------------------------------------------------------*/
1124 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1125 /*-----------------------------------------------------------------*/
1126 void pic16_aopOp (operand *op, iCode *ic, bool result)
1127 {
1128     asmop *aop;
1129     symbol *sym;
1130     int i;
1131
1132     if (!op)
1133         return ;
1134
1135     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1136
1137     /* if this a literal */
1138     if (IS_OP_LITERAL(op)) {
1139         op->aop = aop = newAsmop(AOP_LIT);
1140         aop->aopu.aop_lit = op->operand.valOperand;
1141         aop->size = getSize(operandType(op));
1142         return;
1143     }
1144
1145     {
1146       sym_link *type = operandType(op);
1147 #if 0
1148       if(IS_PTR_CONST(type))
1149 #else
1150       if(IS_CODEPTR(type))
1151 #endif
1152         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1153     }
1154
1155     /* if already has a asmop then continue */
1156     if (op->aop)
1157         return ;
1158
1159     /* if the underlying symbol has a aop */
1160     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1161       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1162         op->aop = OP_SYMBOL(op)->aop;
1163         return;
1164     }
1165
1166     /* if this is a true symbol */
1167     if (IS_TRUE_SYMOP(op)) {    
1168         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1169       op->aop = aopForSym(ic, op, result);
1170       return ;
1171     }
1172
1173     /* this is a temporary : this has
1174     only four choices :
1175     a) register
1176     b) spillocation
1177     c) rematerialize 
1178     d) conditional   
1179     e) can be a return use only */
1180
1181     sym = OP_SYMBOL(op);
1182
1183     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1184     /* if the type is a conditional */
1185     if (sym->regType == REG_CND) {
1186         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1187         aop->size = 0;
1188         return;
1189     }
1190
1191     /* if it is spilt then two situations
1192     a) is rematerialize 
1193     b) has a spill location */
1194     if (sym->isspilt || sym->nRegs == 0) {
1195
1196 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1197       DEBUGpic16_emitcode(";","%d",__LINE__);
1198         /* rematerialize it NOW */
1199         if (sym->remat) {
1200
1201             sym->aop = op->aop = aop = aopForRemat (op);
1202 //            aop->size = getSize(sym->type);
1203 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1204             return;
1205         }
1206
1207 #if 1
1208         if (sym->accuse) {
1209             int i;
1210             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1211             aop->size = getSize(sym->type);
1212             for ( i = 0 ; i < 1 ; i++ ) {
1213                 aop->aopu.aop_str[i] = accUse[i];
1214 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1215             }
1216             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1217             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1218             return;  
1219         }
1220 #endif
1221
1222 #if 1
1223         if (sym->ruonly) {
1224           /*
1225           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1226           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1227           //pic16_allocDirReg (IC_LEFT(ic));
1228           aop->size = getSize(sym->type);
1229           */
1230
1231           unsigned i;
1232
1233           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1234           aop->size = getSize(sym->type);
1235           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1236             aop->aopu.aop_str[i] = fReturn[i];
1237
1238           DEBUGpic16_emitcode(";","%d",__LINE__);
1239           return;
1240         }
1241 #endif
1242         /* else spill location  */
1243         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1244             /* force a new aop if sizes differ */
1245             sym->usl.spillLoc->aop = NULL;
1246         }
1247
1248 #if 0
1249         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1250                             __FUNCTION__,__LINE__,
1251                             sym->usl.spillLoc->rname,
1252                             sym->rname, sym->usl.spillLoc->offset);
1253 #endif
1254
1255         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1256         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1257         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1258           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1259                                                   getSize(sym->type), 
1260                                                   sym->usl.spillLoc->offset, op);
1261         } else {
1262           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1263           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1264           assert (getSize(sym->type) <= 1);
1265           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1266         }
1267         aop->size = getSize(sym->type);
1268
1269         return;
1270     }
1271
1272     {
1273       sym_link *type = operandType(op);
1274 #if 0
1275       if(IS_PTR_CONST(type)) 
1276 #else
1277       if(IS_CODEPTR(type)) 
1278 #endif
1279         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1280     }
1281
1282     /* must be in a register */
1283     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1284     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1285     aop->size = sym->nRegs;
1286     for ( i = 0 ; i < sym->nRegs ;i++)
1287         aop->aopu.aop_reg[i] = sym->regs[i];
1288 }
1289
1290 /*-----------------------------------------------------------------*/
1291 /* pic16_freeAsmop - free up the asmop given to an operand               */
1292 /*----------------------------------------------------------------*/
1293 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1294 {   
1295     asmop *aop ;
1296
1297     if (!op)
1298         aop = aaop;
1299     else 
1300         aop = op->aop;
1301
1302     if (!aop)
1303         return ;
1304
1305     if (aop->freed)
1306         goto dealloc; 
1307
1308     aop->freed = 1;
1309
1310     /* depending on the asmop type only three cases need work AOP_RO
1311        , AOP_R1 && AOP_STK */
1312 #if 1
1313     switch (aop->type) {
1314         case AOP_FSR0 :
1315             if (_G.fsr0Pushed ) {
1316                 if (pop) {
1317                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1318                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1319 //                    pic16_emitcode ("pop","ar0");
1320                     _G.fsr0Pushed--;
1321                 }
1322             }
1323             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1324             break;
1325
1326         case AOP_FSR2 :
1327             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1328             break;
1329
1330         case AOP_R0 :
1331             if (_G.r0Pushed ) {
1332                 if (pop) {
1333                     pic16_emitcode ("pop","ar0");     
1334                     _G.r0Pushed--;
1335                 }
1336             }
1337             bitVectUnSetBit(ic->rUsed,R0_IDX);
1338             break;
1339
1340         case AOP_R1 :
1341             if (_G.r1Pushed ) {
1342                 if (pop) {
1343                     pic16_emitcode ("pop","ar1");
1344                     _G.r1Pushed--;
1345                 }
1346             }
1347             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1348             break;
1349
1350         case AOP_STA:
1351           {
1352             int i;
1353
1354               /* we must store the result on stack */
1355               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1356                 // operands on stack are accessible via "FSR2 + index" with index
1357                 // starting at 2 for arguments and growing from 0 downwards for
1358                 // local variables (index == 0 is not assigned so we add one here)
1359                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1360                 if (soffs <= 0) {
1361                   assert (soffs < 0);
1362                   soffs++;
1363                 } // if
1364                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1365                 for(i=0;i<aop->size;i++) {
1366                   /* initialise for stack access via frame pointer */
1367                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1368                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1369                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1370                 }
1371         
1372                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1373               }
1374
1375               if(!_G.resDirect) {
1376                 for(i=0;i<aop->size;i++)
1377                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1378               }
1379               _G.resDirect = 0;
1380           }
1381           break;
1382 #if 0
1383         case AOP_STK :
1384         {
1385             int sz = aop->size;    
1386             int stk = aop->aopu.aop_stk + aop->size;
1387             bitVectUnSetBit(ic->rUsed,R0_IDX);
1388             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1389
1390             getFreePtr(ic,&aop,FALSE);
1391             
1392             if (options.stack10bit)
1393             {
1394                 /* I'm not sure what to do here yet... */
1395                 /* #STUB */
1396                 fprintf(stderr, 
1397                         "*** Warning: probably generating bad code for "
1398                         "10 bit stack mode.\n");
1399             }
1400             
1401             if (stk) {
1402                 pic16_emitcode ("mov","a,_bp");
1403                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1404                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1405             } else {
1406                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1407             }
1408
1409             while (sz--) {
1410                 pic16_emitcode("pop","acc");
1411                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1412                 if (!sz) break;
1413                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1414             }
1415             op->aop = aop;
1416             pic16_freeAsmop(op,NULL,ic,TRUE);
1417             if (_G.r0Pushed) {
1418                 pic16_emitcode("pop","ar0");
1419                 _G.r0Pushed--;
1420             }
1421
1422             if (_G.r1Pushed) {
1423                 pic16_emitcode("pop","ar1");
1424                 _G.r1Pushed--;
1425             }       
1426         }
1427 #endif
1428
1429     }
1430 #endif
1431
1432 dealloc:
1433     /* all other cases just dealloc */
1434     if (op ) {
1435         op->aop = NULL;
1436         if (IS_SYMOP(op)) {
1437             OP_SYMBOL(op)->aop = NULL;    
1438             /* if the symbol has a spill */
1439             if (SPIL_LOC(op))
1440                 SPIL_LOC(op)->aop = NULL;
1441         }
1442     }
1443 }
1444
1445 /*-----------------------------------------------------------------*/
1446 /* pic16_aopGet - for fetching value of the aop                          */
1447 /*-----------------------------------------------------------------*/
1448 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1449 {
1450     char *s = buffer ;
1451     char *rs;
1452
1453     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1454
1455     /* offset is greater than size then zero */
1456     if (offset > (aop->size - 1) &&
1457         aop->type != AOP_LIT)
1458         return zero;
1459
1460     /* depending on type */
1461     switch (aop->type) {
1462
1463     case AOP_FSR0:
1464     case AOP_FSR2:
1465       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1466       rs = Safe_calloc(1, strlen(s)+1);
1467       strcpy(rs, s);
1468       return (rs);
1469       
1470 #if 0
1471       /* if we need to increment it */
1472       while (offset > aop->coff)
1473         {
1474           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1475           aop->coff++;
1476         }
1477
1478       while (offset < aop->coff)
1479         {
1480           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1481           aop->coff--;
1482         }
1483       aop->coff = offset;
1484       if (aop->paged)
1485         {
1486           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1487           return (dname ? "acc" : "a");
1488         }
1489       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1490       rs = Safe_calloc (1, strlen (s) + 1);
1491       strcpy (rs, s);
1492       return rs;
1493 #endif
1494
1495         
1496     case AOP_IMMD:
1497         if (bit16) 
1498             sprintf (s,"%s",aop->aopu.aop_immd);
1499         else
1500             if (offset) 
1501                 sprintf(s,"(%s >> %d)",
1502                         aop->aopu.aop_immd,
1503                         offset*8);
1504             else
1505                 sprintf(s,"%s",
1506                         aop->aopu.aop_immd);
1507         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1508         rs = Safe_calloc(1,strlen(s)+1);
1509         strcpy(rs,s);   
1510         return rs;
1511         
1512     case AOP_DIR:
1513       if (offset) {
1514         sprintf(s,"(%s + %d)",
1515                 aop->aopu.aop_dir,
1516                 offset);
1517         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1518       } else
1519             sprintf(s,"%s",aop->aopu.aop_dir);
1520         rs = Safe_calloc(1,strlen(s)+1);
1521         strcpy(rs,s);   
1522         return rs;
1523         
1524     case AOP_REG:
1525       //if (dname) 
1526       //    return aop->aopu.aop_reg[offset]->dname;
1527       //else
1528             return aop->aopu.aop_reg[offset]->name;
1529         
1530     case AOP_CRY:
1531       //pic16_emitcode(";","%d",__LINE__);
1532       return aop->aopu.aop_dir;
1533         
1534     case AOP_ACC:
1535         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1536 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1537 //        assert( 0 );
1538 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1539         rs = Safe_strdup("WREG");
1540         return (rs);
1541
1542     case AOP_LIT:
1543         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1544         rs = Safe_calloc(1,strlen(s)+1);
1545         strcpy(rs,s);   
1546         return rs;
1547         
1548     case AOP_STR:
1549         aop->coff = offset ;
1550         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1551             dname)
1552             return "acc";
1553         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1554         
1555         return aop->aopu.aop_str[offset];
1556         
1557     case AOP_PCODE:
1558       {
1559         pCodeOp *pcop = aop->aopu.pcop;
1560         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1561         if(pcop->name) {
1562           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1563           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1564           if (offset) {
1565             sprintf(s,"(%s + %d)", pcop->name, offset);
1566           } else {
1567             sprintf(s,"%s", pcop->name);
1568           }
1569         } else
1570           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1571
1572       }
1573       rs = Safe_calloc(1,strlen(s)+1);
1574       strcpy(rs,s);   
1575       return rs;
1576
1577 #if 0
1578     case AOP_PAGED:
1579       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1580       if (offset) {
1581         sprintf(s,"(%s + %d)",
1582                 aop->aopu.aop_dir,
1583                 offset);
1584       } else
1585             sprintf(s,"%s",aop->aopu.aop_dir);
1586       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1587       rs = Safe_calloc(1,strlen(s)+1);
1588       strcpy(rs,s);   
1589       return rs;
1590 #endif
1591
1592     case AOP_STA:
1593         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1594         return (rs);
1595         
1596     case AOP_STK:
1597 //        pCodeOp *pcop = aop->aop
1598         break;
1599
1600     }
1601
1602     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1603     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1604            "aopget got unsupported aop->type");
1605     exit(0);
1606 }
1607
1608
1609
1610 /* lock has the following meaning: When allocating temporary registers
1611  * for stack variables storage, the value of the temporary register is
1612  * saved on stack. Its value is restored at the end. This procedure is
1613  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1614  * a possibility that before a call to pic16_aopOp, a temporary register
1615  * is allocated for a while and it is freed after some time, this will
1616  * mess the stack and values will not be restored properly. So use lock=1
1617  * to allocate temporary registers used internally by the programmer, and
1618  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1619  * to inform the compiler developer about a possible bug. This is an internal
1620  * feature for developing the compiler -- VR */
1621  
1622 int _TempReg_lock = 0;
1623 /*-----------------------------------------------------------------*/
1624 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1625 /*-----------------------------------------------------------------*/
1626 pCodeOp *pic16_popGetTempReg(int lock)
1627 {
1628   pCodeOp *pcop;
1629   symbol *cfunc;
1630
1631 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1632     if(_TempReg_lock) {
1633 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1634     }
1635     
1636     _TempReg_lock += lock;
1637     
1638     cfunc = currFunc;
1639     currFunc = NULL;
1640
1641     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1642     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1643       PCOR(pcop)->r->wasUsed=1;
1644       PCOR(pcop)->r->isFree=0;
1645
1646       /* push value on stack */
1647       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1648     }
1649
1650     currFunc = cfunc;
1651
1652   return pcop;
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1657 /*                            don't save if inside v               */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1660 {
1661   pCodeOp *pcop;
1662   symbol *cfunc;
1663
1664 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1665
1666     if(_TempReg_lock) {
1667 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1668     }
1669
1670     _TempReg_lock += lock;
1671
1672     cfunc = currFunc;
1673     currFunc = NULL;
1674
1675     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1676     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1677       PCOR(pcop)->r->wasUsed=1;
1678       PCOR(pcop)->r->isFree=0;
1679
1680       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1681       /* push value on stack */
1682         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1683       }
1684     }
1685
1686     currFunc = cfunc;
1687
1688   return pcop;
1689 }
1690
1691
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1694 /*-----------------------------------------------------------------*/
1695 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1696 {
1697   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1698
1699   _TempReg_lock -= lock;
1700
1701   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1702     PCOR(pcop)->r->isFree = 1;
1703     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1704   }
1705 }
1706 /*-----------------------------------------------------------------*/
1707 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1708 /*-----------------------------------------------------------------*/
1709 pCodeOp *pic16_popGetLabel(unsigned int key)
1710 {
1711
1712   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1713
1714   if(key>max_key)
1715     max_key = key;
1716
1717   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1718 }
1719
1720 /*-----------------------------------------------------------------*/
1721 /* pic16_popCopyReg - copy a pcode operator                              */
1722 /*-----------------------------------------------------------------*/
1723 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1724 {
1725   pCodeOpReg *pcor;
1726
1727   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1728   pcor->pcop.type = pc->pcop.type;
1729   if(pc->pcop.name) {
1730     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1731       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1732   } else
1733     pcor->pcop.name = NULL;
1734
1735   pcor->r = pc->r;
1736   pcor->rIdx = pc->rIdx;
1737   pcor->r->wasUsed=1;
1738   pcor->instance = pc->instance;
1739
1740 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1741
1742   return PCOP(pcor);
1743 }
1744
1745 /*-----------------------------------------------------------------*/
1746 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1747 /*-----------------------------------------------------------------*/
1748 pCodeOp *pic16_popGetLit(int lit)
1749 {
1750   return pic16_newpCodeOpLit(lit);
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1755 /*-----------------------------------------------------------------*/
1756 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1757 {
1758   return pic16_newpCodeOpLit2(lit, arg2);
1759 }
1760
1761
1762 /*-----------------------------------------------------------------*/
1763 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1764 /*-----------------------------------------------------------------*/
1765 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1766 {
1767   return pic16_newpCodeOpImmd(name, offset,index, 0);
1768 }
1769
1770
1771 /*-----------------------------------------------------------------*/
1772 /* pic16_popGet - asm operator to pcode operator conversion              */
1773 /*-----------------------------------------------------------------*/
1774 pCodeOp *pic16_popGetWithString(char *str)
1775 {
1776   pCodeOp *pcop;
1777
1778
1779   if(!str) {
1780     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1781     exit (1);
1782   }
1783
1784   pcop = pic16_newpCodeOp(str,PO_STR);
1785
1786   return pcop;
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* pic16_popRegFromString -                                        */
1791 /*-----------------------------------------------------------------*/
1792 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1793 {
1794
1795   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1796   pcop->type = PO_DIR;
1797
1798   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1799   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1800
1801   if(!str)
1802     str = "BAD_STRING";
1803
1804   pcop->name = Safe_calloc(1,strlen(str)+1);
1805   strcpy(pcop->name,str);
1806
1807   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1808
1809   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1810
1811   /* make sure that register doesn't exist,
1812    * and operand isn't NULL
1813    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1814   if((PCOR(pcop)->r == NULL) 
1815     && (op)
1816     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1817 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1818 //              __FUNCTION__, __LINE__, str, size, offset);
1819
1820     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1821     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1822
1823   }
1824   PCOR(pcop)->instance = offset;
1825
1826   return pcop;
1827 }
1828
1829 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1830 {
1831   pCodeOp *pcop;
1832
1833 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1834
1835         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1836         PCOR(pcop)->rIdx = rIdx;
1837         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1838
1839         PCOR(pcop)->r->isFree = 0;
1840         PCOR(pcop)->r->wasUsed = 1;
1841
1842         pcop->type = PCOR(pcop)->r->pc_type;
1843
1844   return pcop;
1845 }
1846
1847 /*---------------------------------------------------------------------------------*/
1848 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1849 /*                 VR 030601                                                       */
1850 /*---------------------------------------------------------------------------------*/
1851 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1852 {
1853   pCodeOpReg2 *pcop2;
1854   pCodeOp *temp;
1855   
1856         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1857
1858         /* comment the following check, so errors to throw up */
1859 //      if(!pcop2)return NULL;
1860
1861         temp = pic16_popGet(aop_dst, offset);
1862         pcop2->pcop2 = temp;
1863         
1864   return PCOP(pcop2);
1865 }
1866
1867
1868
1869 /*--------------------------------------------------------------------------------.-*/
1870 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1871 /*                  VR 030601 , adapted by Hans Dorn                                */
1872 /*--------------------------------------------------------------------------------.-*/
1873 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1874 {
1875   pCodeOpReg2 *pcop2;
1876  
1877         pcop2 = (pCodeOpReg2 *)src;
1878         pcop2->pcop2 = dst;
1879         
1880         return PCOP(pcop2);
1881 }
1882
1883
1884
1885 /*---------------------------------------------------------------------------------*/
1886 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1887 /*                     movff instruction                                           */
1888 /*---------------------------------------------------------------------------------*/
1889 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1890 {
1891   pCodeOpReg2 *pcop2;
1892
1893         if(!noalloc) {
1894                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1895                 pcop2->pcop2 = pic16_popCopyReg(dst);
1896         } else {
1897                 /* the pCodeOp may be already allocated */
1898                 pcop2 = (pCodeOpReg2 *)(src);
1899                 pcop2->pcop2 = (pCodeOp *)(dst);
1900         }
1901
1902   return PCOP(pcop2);
1903 }
1904
1905
1906 /*-----------------------------------------------------------------*/
1907 /* pic16_popGet - asm operator to pcode operator conversion              */
1908 /*-----------------------------------------------------------------*/
1909 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1910 {
1911   //char *s = buffer ;
1912   char *rs;
1913   pCodeOp *pcop;
1914
1915     FENTRY2;
1916     /* offset is greater than
1917     size then zero */
1918
1919 //    if (offset > (aop->size - 1) &&
1920 //        aop->type != AOP_LIT)
1921 //      return NULL;  //zero;
1922
1923     /* depending on type */
1924     switch (aop->type) {
1925         
1926     case AOP_R0:
1927     case AOP_R1:
1928     case AOP_DPTR:
1929     case AOP_DPTR2:
1930         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1931         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1932         assert( 0 );
1933         return NULL;
1934
1935
1936     case AOP_FSR0:
1937     case AOP_FSR2:
1938       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1939       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1940       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1941       PCOR(pcop)->r->wasUsed = 1;
1942       PCOR(pcop)->r->isFree = 0;
1943       
1944       PCOR(pcop)->instance = offset;
1945       pcop->type = PCOR(pcop)->r->pc_type;
1946       return (pcop);
1947
1948     case AOP_IMMD:
1949       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1950       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1951
1952     case AOP_STA:
1953       /* pCodeOp is already allocated from aopForSym */
1954         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1955         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1956           
1957       return (pcop);
1958       
1959     case AOP_ACC:
1960       {
1961         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1962
1963         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1964
1965         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1966         
1967         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1968         PCOR(pcop)->rIdx = rIdx;
1969         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1970         PCOR(pcop)->r->wasUsed=1;
1971         PCOR(pcop)->r->isFree=0;
1972
1973         PCOR(pcop)->instance = offset;
1974         pcop->type = PCOR(pcop)->r->pc_type;
1975 //      rs = aop->aopu.aop_reg[offset]->name;
1976 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1977         return pcop;
1978
1979
1980 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1981 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1982
1983 //      assert( 0 );
1984       }
1985         
1986     case AOP_DIR:
1987       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1988       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1989         
1990 #if 0
1991     case AOP_PAGED:
1992       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1993       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1994 #endif
1995
1996     case AOP_REG:
1997       {
1998         int rIdx;
1999         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2000         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2001
2002         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2003         
2004         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2005 //      pcop->type = PO_GPR_REGISTER;
2006         PCOR(pcop)->rIdx = rIdx;
2007         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2008         PCOR(pcop)->r->wasUsed=1;
2009         PCOR(pcop)->r->isFree=0;
2010
2011         PCOR(pcop)->instance = offset;
2012         pcop->type = PCOR(pcop)->r->pc_type;
2013         
2014         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2015         rs = aop->aopu.aop_reg[offset]->name;
2016         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2017         return pcop;
2018       }
2019
2020     case AOP_CRY:
2021         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2022
2023       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2024       PCOR(pcop)->instance = offset;
2025       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2026       //if(PCOR(pcop)->r == NULL)
2027       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2028       return pcop;
2029         
2030     case AOP_LIT:
2031         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2032       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2033
2034     case AOP_STR:
2035       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2036       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2037
2038       /*
2039       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2040       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2041       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2042       pcop->type = PCOR(pcop)->r->pc_type;
2043       pcop->name = PCOR(pcop)->r->name;
2044
2045       return pcop;
2046       */
2047
2048     case AOP_PCODE:
2049       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2050                           __LINE__, 
2051                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2052       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2053       switch( aop->aopu.pcop->type ) {
2054         case PO_DIR: PCOR(pcop)->instance += offset; break;
2055         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2056         case PO_WREG:
2057             assert (offset==0);
2058             break;
2059         default:
2060           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2061           assert( 0 );  /* should never reach here */;
2062       }
2063       return pcop;
2064     }
2065
2066     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2067            "pic16_popGet got unsupported aop->type");
2068     exit(0);
2069 }
2070 /*-----------------------------------------------------------------*/
2071 /* pic16_aopPut - puts a string for a aop                                */
2072 /*-----------------------------------------------------------------*/
2073 void pic16_aopPut (asmop *aop, char *s, int offset)
2074 {
2075     char *d = buffer ;
2076     symbol *lbl ;
2077
2078     return;
2079
2080     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2081
2082     if (aop->size && offset > ( aop->size - 1)) {
2083         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2084                "pic16_aopPut got offset > aop->size");
2085         exit(0);
2086     }
2087
2088     /* will assign value to value */
2089     /* depending on where it is ofcourse */
2090     switch (aop->type) {
2091     case AOP_DIR:
2092       if (offset) {
2093         sprintf(d,"(%s + %d)",
2094                 aop->aopu.aop_dir,offset);
2095         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2096
2097       } else
2098             sprintf(d,"%s",aop->aopu.aop_dir);
2099         
2100         if (strcmp(d,s)) {
2101           DEBUGpic16_emitcode(";","%d",__LINE__);
2102           if(strcmp(s,"W"))
2103             pic16_emitcode("movf","%s,w",s);
2104           pic16_emitcode("movwf","%s",d);
2105
2106           if(strcmp(s,"W")) {
2107             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2108             if(offset >= aop->size) {
2109               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2110               break;
2111             } else
2112               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2113           }
2114
2115           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2116
2117
2118         }
2119         break;
2120         
2121     case AOP_REG:
2122       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2123         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2124           /*
2125             if (*s == '@'           ||
2126                 strcmp(s,"r0") == 0 ||
2127                 strcmp(s,"r1") == 0 ||
2128                 strcmp(s,"r2") == 0 ||
2129                 strcmp(s,"r3") == 0 ||
2130                 strcmp(s,"r4") == 0 ||
2131                 strcmp(s,"r5") == 0 ||
2132                 strcmp(s,"r6") == 0 || 
2133                 strcmp(s,"r7") == 0 )
2134                 pic16_emitcode("mov","%s,%s  ; %d",
2135                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2136             else
2137           */
2138
2139           if(strcmp(s,"W")==0 )
2140             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2141
2142           pic16_emitcode("movwf","%s",
2143                    aop->aopu.aop_reg[offset]->name);
2144
2145           if(strcmp(s,zero)==0) {
2146             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2147
2148           } else if(strcmp(s,"W")==0) {
2149             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2150             pcop->type = PO_GPR_REGISTER;
2151
2152             PCOR(pcop)->rIdx = -1;
2153             PCOR(pcop)->r = NULL;
2154
2155             DEBUGpic16_emitcode(";","%d",__LINE__);
2156             pcop->name = Safe_strdup(s);
2157             pic16_emitpcode(POC_MOVFW,pcop);
2158             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2159           } else if(strcmp(s,one)==0) {
2160             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2161             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2162           } else {
2163             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2164           }
2165         }
2166         break;
2167         
2168     case AOP_DPTR:
2169     case AOP_DPTR2:
2170     
2171     if (aop->type == AOP_DPTR2)
2172     {
2173         genSetDPTR(1);
2174     }
2175     
2176         if (aop->code) {
2177             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2178                    "pic16_aopPut writting to code space");
2179             exit(0);
2180         }
2181         
2182         while (offset > aop->coff) {
2183             aop->coff++;
2184             pic16_emitcode ("inc","dptr");
2185         }
2186         
2187         while (offset < aop->coff) {
2188             aop->coff-- ;
2189             pic16_emitcode("lcall","__decdptr");
2190         }
2191         
2192         aop->coff = offset;
2193         
2194         /* if not in accumulater */
2195         MOVA(s);        
2196         
2197         pic16_emitcode ("movx","@dptr,a");
2198         
2199     if (aop->type == AOP_DPTR2)
2200     {
2201         genSetDPTR(0);
2202     }
2203         break;
2204         
2205     case AOP_R0:
2206     case AOP_R1:
2207         while (offset > aop->coff) {
2208             aop->coff++;
2209             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2210         }
2211         while (offset < aop->coff) {
2212             aop->coff-- ;
2213             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2214         }
2215         aop->coff = offset;
2216         
2217         if (aop->paged) {
2218             MOVA(s);           
2219             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2220             
2221         } else
2222             if (*s == '@') {
2223                 MOVA(s);
2224                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2225             } else
2226                 if (strcmp(s,"r0") == 0 ||
2227                     strcmp(s,"r1") == 0 ||
2228                     strcmp(s,"r2") == 0 ||
2229                     strcmp(s,"r3") == 0 ||
2230                     strcmp(s,"r4") == 0 ||
2231                     strcmp(s,"r5") == 0 ||
2232                     strcmp(s,"r6") == 0 || 
2233                     strcmp(s,"r7") == 0 ) {
2234                     char buffer[10];
2235                     sprintf(buffer,"a%s",s);
2236                     pic16_emitcode("mov","@%s,%s",
2237                              aop->aopu.aop_ptr->name,buffer);
2238                 } else
2239                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2240         
2241         break;
2242         
2243     case AOP_STK:
2244         if (strcmp(s,"a") == 0)
2245             pic16_emitcode("push","acc");
2246         else
2247             pic16_emitcode("push","%s",s);
2248         
2249         break;
2250         
2251     case AOP_CRY:
2252         /* if bit variable */
2253         if (!aop->aopu.aop_dir) {
2254             pic16_emitcode("clr","a");
2255             pic16_emitcode("rlc","a");
2256         } else {
2257             if (s == zero) 
2258                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2259             else
2260                 if (s == one)
2261                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2262                 else
2263                     if (!strcmp(s,"c"))
2264                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2265                     else {
2266                         lbl = newiTempLabel(NULL);
2267                         
2268                         if (strcmp(s,"a")) {
2269                             MOVA(s);
2270                         }
2271                         pic16_emitcode("clr","c");
2272                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2273                         pic16_emitcode("cpl","c");
2274                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2275                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2276                     }
2277         }
2278         break;
2279         
2280     case AOP_STR:
2281         aop->coff = offset;
2282         if (strcmp(aop->aopu.aop_str[offset],s))
2283             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2284         break;
2285         
2286     case AOP_ACC:
2287         aop->coff = offset;
2288         if (!offset && (strcmp(s,"acc") == 0))
2289             break;
2290         
2291         if (strcmp(aop->aopu.aop_str[offset],s))
2292             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2293         break;
2294
2295     default :
2296         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2297 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2298 //             "pic16_aopPut got unsupported aop->type");
2299 //      exit(0);    
2300     }    
2301
2302 }
2303
2304 /*-----------------------------------------------------------------*/
2305 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2306 /*-----------------------------------------------------------------*/
2307 void pic16_mov2w (asmop *aop, int offset)
2308 {
2309   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2310
2311   if(is_LitAOp(aop))
2312     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2313   else
2314     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2315 }
2316
2317 static void mov2f(asmop *dst, asmop *src, int offset)
2318 {
2319   if(is_LitAOp(src)) {
2320     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2321     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2322   } else {
2323     if(pic16_sameRegsOfs(src, dst, offset))return;
2324     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2325                       pic16_popGet(dst, offset)));
2326   }
2327 }
2328
2329 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2330 {
2331   if(is_LitAOp(src)) {
2332     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2333     pic16_emitpcode(POC_MOVWF, dst);
2334   } else {
2335     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2336   }
2337 }
2338
2339 void pic16_testStackOverflow(void)
2340 {
2341 #define GSTACK_TEST_NAME        "__gstack_test"
2342
2343   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2344   
2345   {
2346     symbol *sym;
2347
2348       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2349       strcpy(sym->rname, GSTACK_TEST_NAME);
2350       checkAddSym(&externs, sym);
2351   }
2352
2353 }
2354
2355 /* push pcop into stack */
2356 void pic16_pushpCodeOp(pCodeOp *pcop)
2357 {
2358 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2359   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2360   if(pic16_options.gstack)
2361     pic16_testStackOverflow();
2362     
2363 }
2364
2365 /* pop pcop from stack */
2366 void pic16_poppCodeOp(pCodeOp *pcop)
2367 {
2368   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2369   if(pic16_options.gstack)
2370     pic16_testStackOverflow();
2371 }
2372
2373
2374 /*-----------------------------------------------------------------*/
2375 /* pushw - pushes wreg to stack                                    */
2376 /*-----------------------------------------------------------------*/
2377 void pushw(void)
2378 {
2379   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2380   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2381   if(pic16_options.gstack)
2382     pic16_testStackOverflow();
2383 }
2384
2385                 
2386 /*-----------------------------------------------------------------*/
2387 /* pushaop - pushes aop to stack                                   */
2388 /*-----------------------------------------------------------------*/
2389 void pushaop(asmop *aop, int offset)
2390 {
2391   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2392
2393   if(is_LitAOp(aop)) {
2394     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2395     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2396   } else {
2397     pic16_emitpcode(POC_MOVFF,
2398       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2399   }
2400
2401   if(pic16_options.gstack)
2402     pic16_testStackOverflow();
2403 }
2404
2405 /*-----------------------------------------------------------------*/
2406 /* popaop - pops aop from stack                                    */
2407 /*-----------------------------------------------------------------*/
2408 void popaop(asmop *aop, int offset)
2409 {
2410   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2411   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2412   if(pic16_options.gstack)
2413     pic16_testStackOverflow();
2414 }
2415
2416 void popaopidx(asmop *aop, int offset, int index)
2417 {
2418   int ofs=1;
2419
2420     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2421
2422     if(STACK_MODEL_LARGE)ofs++;
2423
2424     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2425     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2426     if(pic16_options.gstack)
2427       pic16_testStackOverflow();
2428 }
2429
2430 #if !(USE_GENERIC_SIGNED_SHIFT)
2431 /*-----------------------------------------------------------------*/
2432 /* reAdjustPreg - points a register back to where it should        */
2433 /*-----------------------------------------------------------------*/
2434 static void reAdjustPreg (asmop *aop)
2435 {
2436     int size ;
2437
2438     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2439     aop->coff = 0;
2440     if ((size = aop->size) <= 1)
2441         return ;
2442     size-- ;
2443     switch (aop->type) {
2444         case AOP_R0 :
2445         case AOP_R1 :
2446             while (size--)
2447                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2448             break;          
2449         case AOP_DPTR :
2450         case AOP_DPTR2:
2451             if (aop->type == AOP_DPTR2)
2452             {
2453                 genSetDPTR(1);
2454             } 
2455             while (size--)
2456             {
2457                 pic16_emitcode("lcall","__decdptr");
2458             }
2459                 
2460             if (aop->type == AOP_DPTR2)
2461             {
2462                 genSetDPTR(0);
2463             }                
2464             break;  
2465
2466     }   
2467
2468 }
2469 #endif
2470
2471 #if 0
2472 /*-----------------------------------------------------------------*/
2473 /* opIsGptr: returns non-zero if the passed operand is             */   
2474 /* a generic pointer type.                                         */
2475 /*-----------------------------------------------------------------*/ 
2476 static int opIsGptr(operand *op)
2477 {
2478     sym_link *type = operandType(op);
2479     
2480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2481     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2482     {
2483         return 1;
2484     }
2485     return 0;        
2486 }
2487 #endif
2488
2489 /*-----------------------------------------------------------------*/
2490 /* pic16_getDataSize - get the operand data size                         */
2491 /*-----------------------------------------------------------------*/
2492 int pic16_getDataSize(operand *op)
2493 {
2494     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2495
2496
2497     return AOP_SIZE(op);
2498
2499     // tsd- in the pic port, the genptr size is 1, so this code here
2500     // fails. ( in the 8051 port, the size was 4).
2501 #if 0
2502     int size;
2503     size = AOP_SIZE(op);
2504     if (size == GPTRSIZE)
2505     {
2506         sym_link *type = operandType(op);
2507         if (IS_GENPTR(type))
2508         {
2509             /* generic pointer; arithmetic operations
2510              * should ignore the high byte (pointer type).
2511              */
2512             size--;
2513     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2514         }
2515     }
2516     return size;
2517 #endif
2518 }
2519
2520 /*-----------------------------------------------------------------*/
2521 /* pic16_outAcc - output Acc                                             */
2522 /*-----------------------------------------------------------------*/
2523 void pic16_outAcc(operand *result)
2524 {
2525   int size,offset;
2526   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2527   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2528
2529
2530   size = pic16_getDataSize(result);
2531   if(size){
2532     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2533     size--;
2534     offset = 1;
2535     /* unsigned or positive */
2536     while(size--)
2537       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2538   }
2539
2540 }
2541
2542 /*-----------------------------------------------------------------*/
2543 /* pic16_outBitC - output a bit C                                  */
2544 /*                 Move to result the value of Carry flag -- VR    */
2545 /*-----------------------------------------------------------------*/
2546 void pic16_outBitC(operand *result)
2547 {
2548   int i;
2549
2550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2551
2552     /* if the result is bit */
2553     if (AOP_TYPE(result) == AOP_CRY) {
2554         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2555         pic16_aopPut(AOP(result),"c",0);
2556     } else {
2557
2558         i = AOP_SIZE(result);
2559         while(i--) {
2560                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2561         }
2562         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2563     }
2564 }
2565
2566 /*-----------------------------------------------------------------*/
2567 /* pic16_outBitOp - output a bit from Op                           */
2568 /*                 Move to result the value of set/clr op -- VR    */
2569 /*-----------------------------------------------------------------*/
2570 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2571 {
2572   int i;
2573
2574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2575
2576     /* if the result is bit */
2577     if (AOP_TYPE(result) == AOP_CRY) {
2578         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2579         pic16_aopPut(AOP(result),"c",0);
2580     } else {
2581
2582         i = AOP_SIZE(result);
2583         while(i--) {
2584                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2585         }
2586         pic16_emitpcode(POC_RRCF, pcop);          
2587         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2588     }
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2593 /*-----------------------------------------------------------------*/
2594 void pic16_toBoolean(operand *oper)
2595 {
2596     int size = AOP_SIZE(oper) - 1;
2597     int offset = 1;
2598
2599     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2600
2601     if ( AOP_TYPE(oper) != AOP_ACC) {
2602       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2603     }
2604     while (size--) {
2605       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2606     }
2607 }
2608
2609
2610 #if !defined(GEN_Not)
2611 /*-----------------------------------------------------------------*/
2612 /* genNot - generate code for ! operation                          */
2613 /*-----------------------------------------------------------------*/
2614 static void pic16_genNot (iCode *ic)
2615 {
2616   symbol *tlbl;
2617   int size;
2618
2619   FENTRY;
2620   /* assign asmOps to operand & result */
2621   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2622   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2623
2624   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2625   /* if in bit space then a special case */
2626   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2627     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2628       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2629       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2630     } else {
2631       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2632       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2633       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2634     }
2635     goto release;
2636   }
2637
2638   size = AOP_SIZE(IC_LEFT(ic));
2639   if(size == 1) {
2640     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2641     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2642     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2643     goto release;
2644   }
2645   pic16_toBoolean(IC_LEFT(ic));
2646
2647   tlbl = newiTempLabel(NULL);
2648   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2649   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2650   pic16_outBitC(IC_RESULT(ic));
2651
2652  release:    
2653   /* release the aops */
2654   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2655   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2656 }
2657 #endif
2658
2659
2660 #if !defined(GEN_Cpl)
2661 /*-----------------------------------------------------------------*/
2662 /* genCpl - generate code for complement                           */
2663 /*-----------------------------------------------------------------*/
2664 static void pic16_genCpl (iCode *ic)
2665 {
2666   int offset = 0;
2667   int size ;
2668
2669     FENTRY;
2670     /* assign asmOps to operand & result */
2671     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2672     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2673
2674     /* if both are in bit space then 
2675     a special case */
2676     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2677         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2678
2679         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2680         pic16_emitcode("cpl","c"); 
2681         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2682         goto release; 
2683     } 
2684
2685     size = AOP_SIZE(IC_RESULT(ic));
2686     while (size--) {
2687 /*
2688         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2689         MOVA(l);       
2690         pic16_emitcode("cpl","a");
2691         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2692 */
2693         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2694               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2695         } else {
2696                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2697                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2698         }
2699         offset++;
2700
2701     }
2702
2703
2704 release:
2705     /* release the aops */
2706     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2707     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2708 }
2709 #endif
2710
2711 /*-----------------------------------------------------------------*/
2712 /* genUminusFloat - unary minus for floating points                */
2713 /*-----------------------------------------------------------------*/
2714 static void genUminusFloat(operand *op,operand *result)
2715 {
2716   int size ,offset =0 ;
2717   
2718     FENTRY;
2719     /* for this we just need to flip the 
2720     first it then copy the rest in place */
2721     size = AOP_SIZE(op);
2722
2723     while(size--) {
2724       mov2f(AOP(result), AOP(op), offset);
2725       offset++;
2726     }
2727     
2728     /* toggle the MSB's highest bit */
2729     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2730 }
2731
2732 /*-----------------------------------------------------------------*/
2733 /* genUminus - unary minus code generation                         */
2734 /*-----------------------------------------------------------------*/
2735 static void genUminus (iCode *ic)
2736 {
2737   int size, i;
2738   sym_link *optype, *rtype;
2739   symbol *label;
2740   int needLabel=0;
2741
2742     FENTRY;     
2743     
2744     /* assign asmops */
2745     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2746     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2747
2748     /* if both in bit space then special case */
2749     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2750       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2751         
2752         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2753         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2754         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2755         goto release; 
2756     } 
2757
2758     optype = operandType(IC_LEFT(ic));
2759     rtype = operandType(IC_RESULT(ic));
2760
2761     /* if float then do float stuff */
2762     if (IS_FLOAT(optype)) {
2763       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2764       goto release;
2765     }
2766
2767     /* otherwise subtract from zero by taking the 2's complement */
2768     size = AOP_SIZE(IC_LEFT(ic));
2769     label = newiTempLabel ( NULL );
2770     
2771     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2772       for (i=size-1; i > 0; i--) {
2773         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2774       } // for
2775       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2776       for (i=1; i < size; i++) {
2777         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2778         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2779       } // for
2780     } else {
2781       for (i=size-1; i >= 0; i--) {
2782         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2783         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2784       } // for
2785       if (size > 1) {
2786         for (i=0; i < size-2; i++) {
2787           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2788           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2789         } // for
2790         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2791       } // if
2792       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2793     }
2794     if (needLabel)
2795       pic16_emitpLabel (label->key);
2796
2797 release:
2798     /* release the aops */
2799     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2800     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2801 }
2802
2803 #if 0
2804 /*-----------------------------------------------------------------*/
2805 /* saveRegisters - will look for a call and save the registers     */
2806 /*-----------------------------------------------------------------*/
2807 static void saveRegisters(iCode *lic) 
2808 {
2809     int i;
2810     iCode *ic;
2811     bitVect *rsave;
2812     sym_link *dtype;
2813
2814     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2815     /* look for call */
2816     for (ic = lic ; ic ; ic = ic->next) 
2817         if (ic->op == CALL || ic->op == PCALL)
2818             break;
2819
2820     if (!ic) {
2821         fprintf(stderr,"found parameter push with no function call\n");
2822         return ;
2823     }
2824
2825     /* if the registers have been saved already then
2826     do nothing */
2827     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2828         return ;
2829
2830     /* find the registers in use at this time 
2831     and push them away to safety */
2832     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2833                           ic->rUsed);
2834
2835     ic->regsSaved = 1;
2836     if (options.useXstack) {
2837         if (bitVectBitValue(rsave,R0_IDX))
2838             pic16_emitcode("mov","b,r0");
2839         pic16_emitcode("mov","r0,%s",spname);
2840         for (i = 0 ; i < pic16_nRegs ; i++) {
2841             if (bitVectBitValue(rsave,i)) {
2842                 if (i == R0_IDX)
2843                     pic16_emitcode("mov","a,b");
2844                 else
2845                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2846                 pic16_emitcode("movx","@r0,a");
2847                 pic16_emitcode("inc","r0");
2848             }
2849         }
2850         pic16_emitcode("mov","%s,r0",spname);
2851         if (bitVectBitValue(rsave,R0_IDX))
2852             pic16_emitcode("mov","r0,b");           
2853     }// else
2854     //for (i = 0 ; i < pic16_nRegs ; i++) {
2855     //    if (bitVectBitValue(rsave,i))
2856     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2857     //}
2858
2859     dtype = operandType(IC_LEFT(ic));
2860     if (currFunc && dtype && 
2861         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2862         IFFUNC_ISISR(currFunc->type) &&
2863         !ic->bankSaved) 
2864
2865         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2866
2867 }
2868 /*-----------------------------------------------------------------*/
2869 /* unsaveRegisters - pop the pushed registers                      */
2870 /*-----------------------------------------------------------------*/
2871 static void unsaveRegisters (iCode *ic)
2872 {
2873     int i;
2874     bitVect *rsave;
2875
2876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2877     /* find the registers in use at this time 
2878     and push them away to safety */
2879     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2880                           ic->rUsed);
2881     
2882     if (options.useXstack) {
2883         pic16_emitcode("mov","r0,%s",spname);   
2884         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2885             if (bitVectBitValue(rsave,i)) {
2886                 pic16_emitcode("dec","r0");
2887                 pic16_emitcode("movx","a,@r0");
2888                 if (i == R0_IDX)
2889                     pic16_emitcode("mov","b,a");
2890                 else
2891                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2892             }       
2893
2894         }
2895         pic16_emitcode("mov","%s,r0",spname);
2896         if (bitVectBitValue(rsave,R0_IDX))
2897             pic16_emitcode("mov","r0,b");
2898     } //else
2899     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2900     //    if (bitVectBitValue(rsave,i))
2901     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2902     //}
2903
2904 }  
2905 #endif
2906
2907 #if 0  // patch 14
2908 /*-----------------------------------------------------------------*/
2909 /* pushSide -                                                      */
2910 /*-----------------------------------------------------------------*/
2911 static void pushSide(operand * oper, int size)
2912 {
2913         int offset = 0;
2914     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2915         while (size--) {
2916                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2917                 if (AOP_TYPE(oper) != AOP_REG &&
2918                     AOP_TYPE(oper) != AOP_DIR &&
2919                     strcmp(l,"a") ) {
2920                         pic16_emitcode("mov","a,%s",l);
2921                         pic16_emitcode("push","acc");
2922                 } else
2923                         pic16_emitcode("push","%s",l);
2924         }
2925 }
2926 #endif // patch 14
2927
2928 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2929 {
2930   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2931     pic16_emitpcode(POC_MOVFW, src);
2932     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2933   } else {
2934     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2935         src, pic16_popGet(AOP(op), offset)));
2936   }
2937 }
2938
2939
2940 /*-----------------------------------------------------------------*/
2941 /* assignResultValue - assign results to oper, rescall==1 is       */
2942 /*                     called from genCall() or genPcall()         */
2943 /*-----------------------------------------------------------------*/
2944 static void assignResultValue(operand * oper, int rescall)
2945 {
2946   int size = AOP_SIZE(oper);
2947   int offset=0;
2948   
2949     FENTRY2;
2950 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2951     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2952
2953     if(rescall) {
2954       /* assign result from a call/pcall function() */
2955                 
2956       /* function results are stored in a special order,
2957        * see top of file with Function return policy, or manual */
2958
2959       if(size <= 4) {
2960         /* 8-bits, result in WREG */
2961         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2962                         
2963         if(size>1) {
2964           /* 16-bits, result in PRODL:WREG */
2965           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2966         }
2967                         
2968         if(size>2) {
2969           /* 24-bits, result in PRODH:PRODL:WREG */
2970           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2971         }
2972                         
2973         if(size>3) {
2974           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2975           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2976         }
2977       
2978       } else {
2979         /* >32-bits, result on stack, and FSR0 points to beginning.
2980          * Fix stack when done */
2981         /* FIXME FIXME */
2982 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2983         while (size--) {
2984 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2985 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2986                 
2987           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2988           GpsuedoStkPtr++;
2989         }
2990                         
2991         /* fix stack */
2992         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2993         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2994         if(STACK_MODEL_LARGE) {
2995           emitSKPNC;
2996           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2997         }
2998       }                 
2999     } else {
3000       int areg = 0;             /* matching argument register */
3001       
3002 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3003       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3004
3005
3006       /* its called from genReceive (probably) -- VR */
3007       /* I hope this code will not be called from somewhere else in the future! 
3008        * We manually set the pseudo stack pointer in genReceive. - dw
3009        */
3010       if(!GpsuedoStkPtr && _G.useWreg) {
3011 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3012
3013         /* The last byte in the assignment is in W */
3014         if(areg <= GpsuedoStkPtr) {
3015           size--;
3016           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3017           offset++;
3018 //          debugf("receive from WREG\n", 0);
3019         }
3020         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3021       }
3022 //      GpsuedoStkPtr++;
3023       _G.stack_lat = AOP_SIZE(oper)-1;
3024
3025       while (size) {
3026         size--;
3027         GpsuedoStkPtr++;
3028         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3029 //        debugf("receive from STACK\n", 0);
3030         offset++;
3031       }
3032     }
3033 }
3034
3035
3036 /*-----------------------------------------------------------------*/
3037 /* genIpush - generate code for pushing this gets a little complex */
3038 /*-----------------------------------------------------------------*/
3039 static void genIpush (iCode *ic)
3040 {
3041 //  int size, offset=0;
3042
3043   FENTRY;
3044   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3045
3046   if(ic->parmPush) {
3047     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3048
3049     /* send to stack as normal */
3050     addSet(&_G.sendSet,ic);
3051 //    addSetHead(&_G.sendSet,ic);
3052     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3053   }
3054
3055         
3056 #if 0
3057     int size, offset = 0 ;
3058     char *l;
3059
3060
3061     /* if this is not a parm push : ie. it is spill push 
3062     and spill push is always done on the local stack */
3063     if (!ic->parmPush) {
3064
3065         /* and the item is spilt then do nothing */
3066         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3067             return ;
3068
3069         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3070         size = AOP_SIZE(IC_LEFT(ic));
3071         /* push it on the stack */
3072         while(size--) {
3073             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3074             if (*l == '#') {
3075                 MOVA(l);
3076                 l = "acc";
3077             }
3078             pic16_emitcode("push","%s",l);
3079         }
3080         return ;        
3081     }
3082
3083     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3084 #endif
3085 }
3086
3087 /*-----------------------------------------------------------------*/
3088 /* genIpop - recover the registers: can happen only for spilling   */
3089 /*-----------------------------------------------------------------*/
3090 static void genIpop (iCode *ic)
3091 {
3092   FENTRY;
3093   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3094 #if 0
3095     int size,offset ;
3096
3097
3098     /* if the temp was not pushed then */
3099     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3100         return ;
3101
3102     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3103     size = AOP_SIZE(IC_LEFT(ic));
3104     offset = (size-1);
3105     while (size--) 
3106         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3107                                    FALSE,TRUE));
3108
3109     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3110 #endif
3111 }
3112
3113 #if 0
3114 /*-----------------------------------------------------------------*/
3115 /* unsaverbank - restores the resgister bank from stack            */
3116 /*-----------------------------------------------------------------*/
3117 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3118 {
3119   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3120 #if 0
3121     int i;
3122     asmop *aop ;
3123     regs *r = NULL;
3124
3125     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3126     if (popPsw) {
3127         if (options.useXstack) {
3128             aop = newAsmop(0);
3129             r = getFreePtr(ic,&aop,FALSE);
3130             
3131             
3132             pic16_emitcode("mov","%s,_spx",r->name);
3133             pic16_emitcode("movx","a,@%s",r->name);
3134             pic16_emitcode("mov","psw,a");
3135             pic16_emitcode("dec","%s",r->name);
3136             
3137         }else
3138             pic16_emitcode ("pop","psw");
3139     }
3140
3141     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3142         if (options.useXstack) {       
3143             pic16_emitcode("movx","a,@%s",r->name);
3144             //pic16_emitcode("mov","(%s+%d),a",
3145             //       regspic16[i].base,8*bank+regspic16[i].offset);
3146             pic16_emitcode("dec","%s",r->name);
3147
3148         } else 
3149           pic16_emitcode("pop",""); //"(%s+%d)",
3150         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3151     }
3152
3153     if (options.useXstack) {
3154
3155         pic16_emitcode("mov","_spx,%s",r->name);
3156         pic16_freeAsmop(NULL,aop,ic,TRUE);
3157
3158     }
3159 #endif 
3160 }
3161
3162 /*-----------------------------------------------------------------*/
3163 /* saverbank - saves an entire register bank on the stack          */
3164 /*-----------------------------------------------------------------*/
3165 static void saverbank (int bank, iCode *ic, bool pushPsw)
3166 {
3167   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3168 #if 0
3169     int i;
3170     asmop *aop ;
3171     regs *r = NULL;
3172
3173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3174     if (options.useXstack) {
3175
3176         aop = newAsmop(0);
3177         r = getFreePtr(ic,&aop,FALSE);  
3178         pic16_emitcode("mov","%s,_spx",r->name);
3179
3180     }
3181
3182     for (i = 0 ; i < pic16_nRegs ;i++) {
3183         if (options.useXstack) {
3184             pic16_emitcode("inc","%s",r->name);
3185             //pic16_emitcode("mov","a,(%s+%d)",
3186             //         regspic16[i].base,8*bank+regspic16[i].offset);
3187             pic16_emitcode("movx","@%s,a",r->name);           
3188         } else 
3189           pic16_emitcode("push","");// "(%s+%d)",
3190                      //regspic16[i].base,8*bank+regspic16[i].offset);
3191     }
3192     
3193     if (pushPsw) {
3194         if (options.useXstack) {
3195             pic16_emitcode("mov","a,psw");
3196             pic16_emitcode("movx","@%s,a",r->name);     
3197             pic16_emitcode("inc","%s",r->name);
3198             pic16_emitcode("mov","_spx,%s",r->name);       
3199             pic16_freeAsmop (NULL,aop,ic,TRUE);
3200             
3201         } else
3202             pic16_emitcode("push","psw");
3203         
3204         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3205     }
3206     ic->bankSaved = 1;
3207 #endif
3208 }
3209 #endif  /* 0 */
3210
3211
3212 static int wparamCmp(void *p1, void *p2)
3213 {
3214   return (!strcmp((char *)p1, (char *)p2));
3215 }
3216
3217 int inWparamList(char *s)
3218 {
3219   return isinSetWith(wparamList, s, wparamCmp);
3220
3221
3222
3223 /*-----------------------------------------------------------------*/
3224 /* genCall - generates a call statement                            */
3225 /*-----------------------------------------------------------------*/
3226 static void genCall (iCode *ic)
3227 {
3228   sym_link *ftype;   
3229   int stackParms=0;
3230   int use_wreg=0;
3231   int inwparam=0;
3232   char *fname;
3233   
3234     FENTRY;
3235
3236     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3237     /* if caller saves & we have not saved then */
3238 //    if (!ic->regsSaved)
3239 //      saveRegisters(ic);
3240
3241         /* initialise stackParms for IPUSH pushes */
3242 //      stackParms = psuedoStkPtr;
3243 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3244     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3245     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3246
3247 #if 0
3248     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3249 #endif
3250
3251     /* if send set is not empty the assign */
3252     if (_G.sendSet) {
3253       iCode *sic;
3254       int psuedoStkPtr=-1; 
3255       int firstTimeThruLoop = 1;
3256
3257
3258         /* reverse sendSet if function is not reentrant */
3259         if(!IFFUNC_ISREENT(ftype))
3260           _G.sendSet = reverseSet(_G.sendSet);
3261
3262         /* First figure how many parameters are getting passed */
3263         stackParms = 0;
3264         use_wreg = 0;
3265         
3266         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3267           int size;
3268 //          int offset = 0;
3269
3270             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3271             size = AOP_SIZE(IC_LEFT(sic));
3272
3273             stackParms += size;
3274
3275             /* pass the last byte through WREG */
3276             if(inwparam) {
3277
3278               while (size--) {
3279                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3280                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3281                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3282
3283                 if(!firstTimeThruLoop) {
3284                   /* If this is not the first time we've been through the loop
3285                    * then we need to save the parameter in a temporary
3286                    * register. The last byte of the last parameter is
3287                    * passed in W. */
3288
3289                   pushw();
3290 //                  --psuedoStkPtr;             // sanity check
3291                   use_wreg = 1;
3292                 }
3293                 
3294                 firstTimeThruLoop=0;
3295
3296                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3297
3298 //                offset++;
3299               }
3300             } else {
3301               /* all arguments are passed via stack */
3302               use_wreg = 0;
3303
3304               while (size--) {
3305                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3306                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3307                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3308
3309 //                pushaop(AOP(IC_LEFT(sic)), size);
3310                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3311                 pushw();
3312               }
3313             }
3314
3315             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3316           }
3317
3318           if(inwparam) {
3319             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3320               pushw();  /* save last parameter to stack if functions has varargs */
3321               use_wreg = 0;
3322             } else
3323               use_wreg = 1;
3324           } else use_wreg = 0;
3325
3326           _G.stackRegSet = _G.sendSet;
3327           _G.sendSet = NULL;
3328     }
3329
3330     /* make the call */
3331     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3332
3333     GpsuedoStkPtr=0;
3334     
3335     /* if we need to assign a result value */
3336     if ((IS_ITEMP(IC_RESULT(ic))
3337           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3338               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3339         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3340
3341       _G.accInUse++;
3342       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3343       _G.accInUse--;
3344
3345       assignResultValue(IC_RESULT(ic), 1);
3346
3347       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3348                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3349                 
3350       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3351     }
3352
3353     if(!stackParms && ic->parmBytes) {
3354       stackParms = ic->parmBytes;
3355     }
3356       
3357     stackParms -= use_wreg;
3358     
3359     if(stackParms>0) {
3360       if(stackParms == 1) {
3361         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3362       } else {
3363         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3364         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3365       }
3366       if(STACK_MODEL_LARGE) {
3367         emitSKPNC;
3368         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3369       }
3370     }
3371
3372 #if 0
3373     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3374 #endif
3375
3376     /* adjust the stack for parameters if required */
3377 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3378
3379 #if 0
3380       /* if register bank was saved then pop them */
3381       if (ic->bankSaved)
3382         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3383
3384       /* if we hade saved some registers then unsave them */
3385       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3386         unsaveRegisters (ic);
3387 #endif
3388 }
3389
3390
3391
3392 /*-----------------------------------------------------------------*/
3393 /* genPcall - generates a call by pointer statement                */
3394 /*            new version, created from genCall - HJD              */
3395 /*-----------------------------------------------------------------*/
3396 static void genPcall (iCode *ic)
3397 {
3398   sym_link *ftype, *fntype;
3399   int stackParms=0;
3400   symbol *retlbl = newiTempLabel(NULL);
3401   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3402   
3403     FENTRY;
3404
3405     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3406     fntype = operandType( IC_LEFT(ic) )->next;
3407
3408     /* if send set is not empty the assign */
3409     if (_G.sendSet) {
3410       iCode *sic;
3411       int psuedoStkPtr=-1; 
3412
3413       /* reverse sendSet if function is not reentrant */
3414       if(!IFFUNC_ISREENT(fntype))
3415         _G.sendSet = reverseSet(_G.sendSet);
3416
3417       stackParms = 0;
3418       
3419       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3420         int size;
3421
3422           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3423           size = AOP_SIZE(IC_LEFT(sic));
3424           stackParms += size;
3425
3426           /* all parameters are passed via stack, since WREG is clobbered
3427            * by the calling sequence */
3428           while (size--) {
3429             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3430             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3431             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3432
3433             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3434             pushw();
3435           }
3436
3437           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3438       }
3439
3440       _G.stackRegSet = _G.sendSet;
3441       _G.sendSet = NULL;
3442     }
3443
3444     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3445
3446     // push return address
3447     // push $ on return stack, then replace with retlbl
3448
3449     /* Thanks to Thorsten Klose for pointing out that the following
3450      * snippet should be interrupt safe */
3451     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3452     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3453
3454     pic16_emitpcodeNULLop(POC_PUSH);
3455
3456     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3457     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3458     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3459     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3460     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3461     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3462
3463
3464     /* restore interrupt control register */
3465     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3466     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3467
3468     /* make the call by writing the pointer into pc */
3469     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3470     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3471
3472     // note: MOVFF to PCL not allowed
3473     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3474     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3475
3476
3477     /* return address is here: (X) */
3478     pic16_emitpLabelFORCE(retlbl->key);
3479
3480     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3481
3482     GpsuedoStkPtr=0;
3483     /* if we need assign a result value */
3484     if ((IS_ITEMP(IC_RESULT(ic))
3485           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3486               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3487         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3488
3489       _G.accInUse++;
3490       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3491       _G.accInUse--;
3492
3493       assignResultValue(IC_RESULT(ic), 1);
3494
3495       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3496               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3497                 
3498       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3499     }
3500
3501 //    stackParms -= use_wreg;
3502     
3503     if(stackParms>0) {
3504       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3505       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3506       if(STACK_MODEL_LARGE) {
3507         emitSKPNC;
3508         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3509       }
3510     }
3511 }
3512
3513 /*-----------------------------------------------------------------*/
3514 /* resultRemat - result  is rematerializable                       */
3515 /*-----------------------------------------------------------------*/
3516 static int resultRemat (iCode *ic)
3517 {
3518   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3519   if (SKIP_IC(ic) || ic->op == IFX)
3520     return 0;
3521
3522   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3523     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3524     if (sym->remat && !POINTER_SET(ic)) 
3525       return 1;
3526   }
3527
3528   return 0;
3529 }
3530
3531 #if defined(__BORLANDC__) || defined(_MSC_VER)
3532 #define STRCASECMP stricmp
3533 #else
3534 #define STRCASECMP strcasecmp
3535 #endif
3536
3537 #if 0
3538 /*-----------------------------------------------------------------*/
3539 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3540 /*-----------------------------------------------------------------*/
3541 static bool inExcludeList(char *s)
3542 {
3543   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3544     int i =0;
3545     
3546     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3547     if (options.excludeRegs[i] &&
3548     STRCASECMP(options.excludeRegs[i],"none") == 0)
3549         return FALSE ;
3550
3551     for ( i = 0 ; options.excludeRegs[i]; i++) {
3552         if (options.excludeRegs[i] &&
3553         STRCASECMP(s,options.excludeRegs[i]) == 0)
3554             return TRUE;
3555     }
3556     return FALSE ;
3557 }
3558 #endif
3559
3560 /*-----------------------------------------------------------------*/
3561 /* genFunction - generated code for function entry                 */
3562 /*-----------------------------------------------------------------*/
3563 static void genFunction (iCode *ic)
3564 {
3565   symbol *sym;
3566   sym_link *ftype;
3567   
3568     FENTRY;
3569     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3570
3571     pic16_labelOffset += (max_key+4);
3572     max_key=0;
3573     GpsuedoStkPtr=0;
3574     _G.nRegsSaved = 0;
3575         
3576     ftype = operandType(IC_LEFT(ic));
3577     sym = OP_SYMBOL(IC_LEFT(ic));
3578
3579     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3580       /* create an absolute section at the interrupt vector:
3581        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3582       symbol *asym;
3583       char asymname[128];
3584       pBlock *apb;
3585
3586 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3587
3588 #if 0
3589         {
3590           int i, found=-1;
3591
3592             sym = OP_SYMBOL( IC_LEFT(ic));
3593             for(i=0;i<=2;i++) {
3594               if(interrupts[i]->name
3595                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3596                   found = i;
3597                   break;
3598               }
3599             }
3600                         
3601             if(found == -1) {
3602               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3603                             __FILE__, __LINE__, sym->name);
3604 //              assert( 0 );
3605             }
3606             _G.interruptvector = found;
3607         }
3608 #endif
3609
3610         if(FUNC_INTNO(sym->type) == 256)
3611           sprintf(asymname, "ivec_%s", sym->name);
3612         else
3613           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3614         asym = newSymbol(asymname, 0);
3615
3616         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3617         pic16_addpBlock( apb );
3618
3619         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3620         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3621         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3622                 
3623         /* mark the end of this tiny function */
3624         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3625
3626         {
3627           absSym *abSym;
3628
3629             abSym = Safe_calloc(1, sizeof(absSym));
3630             strcpy(abSym->name, asymname);
3631
3632             switch( FUNC_INTNO(sym->type) ) {
3633               case 0: abSym->address = 0x000000; break;
3634               case 1: abSym->address = 0x000008; break;
3635               case 2: abSym->address = 0x000018; break;
3636               
3637               default:
3638                 abSym->address = -1; break;
3639             }
3640
3641             /* relocate interrupt vectors if needed */
3642             if(abSym->address != -1)
3643               abSym->address += pic16_options.ivt_loc;
3644
3645             addSet(&absSymSet, abSym);
3646         }
3647     }
3648
3649     /* create the function header */
3650     pic16_emitcode(";","-----------------------------------------");
3651     pic16_emitcode(";"," function %s",sym->name);
3652     pic16_emitcode(";","-----------------------------------------");
3653
3654     pic16_emitcode("","%s:",sym->rname);
3655     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3656
3657
3658     {
3659       absSym *ab;
3660
3661         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3662           if(!strcmp(ab->name, sym->rname)) {
3663             pic16_pBlockConvert2Absolute(pb);
3664             break;
3665           }
3666         }
3667     }
3668
3669
3670     if(IFFUNC_ISNAKED(ftype)) {
3671       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3672       return;
3673     }
3674         
3675     /* if critical function then turn interrupts off */
3676     if (IFFUNC_ISCRITICAL(ftype)) {
3677       //pic16_emitcode("clr","ea");
3678     }
3679
3680     _G.fregsUsed = sym->regsUsed;
3681
3682     /* if this is an interrupt service routine then
3683      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3684     if (IFFUNC_ISISR(sym->type)) {
3685         _G.usefastretfie = 1;   /* use shadow registers by default */
3686         
3687         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3688         if(!FUNC_ISSHADOWREGS(sym->type)) {
3689           /* do not save WREG,STATUS,BSR for high priority interrupts
3690            * because they are stored in the hardware shadow registers already */
3691           _G.usefastretfie = 0;
3692           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3693           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3694           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3695         }
3696
3697         /* these should really be optimized somehow, because not all
3698          * interrupt handlers modify them */
3699         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3700         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3701         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3702         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3703         
3704 //        pic16_pBlockConvert2ISR(pb);
3705                 
3706     }
3707
3708     /* emit code to setup stack frame if user enabled,
3709      * and function is not main() */
3710     
3711     //fprintf(stderr, "function name: %s\n", sym->name);
3712     if(strcmp(sym->name, "main")) {
3713       if(0 || !options.ommitFramePtr || sym->regsUsed) {
3714         /* setup the stack frame */
3715         if(STACK_MODEL_LARGE)
3716           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3717         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3718
3719         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3720         if(STACK_MODEL_LARGE)
3721           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3722       }
3723     }
3724
3725     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3726           && sym->stack) {
3727
3728       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3729
3730       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3731       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3732       emitSKPC;
3733       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3734     }
3735           
3736     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3737       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3738         _G.useWreg = 0;
3739       else
3740         _G.useWreg = 1;
3741     } else
3742       _G.useWreg = 0;
3743
3744     /* if callee-save to be used for this function
3745      * then save the registers being used in this function */
3746 //    if (IFFUNC_CALLEESAVES(sym->type))
3747     {
3748       int i;
3749
3750         /* if any registers used */
3751         if (sym->regsUsed) {
3752           /* save the registers used */
3753           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3754           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3755           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3756             if (bitVectBitValue(sym->regsUsed,i)) {
3757               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3758               _G.nRegsSaved++;
3759
3760               if(!pic16_regWithIdx(i)->wasUsed) {
3761                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3762                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3763                 pic16_regWithIdx(i)->wasUsed = 1;
3764               }
3765             }
3766           }
3767           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3768         }
3769     }
3770         
3771     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3772 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3773 }
3774
3775 /*-----------------------------------------------------------------*/
3776 /* genEndFunction - generates epilogue for functions               */
3777 /*-----------------------------------------------------------------*/
3778 static void genEndFunction (iCode *ic)
3779 {
3780   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3781
3782     FENTRY;
3783
3784     if(IFFUNC_ISNAKED(sym->type)) {
3785       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3786       return;
3787     }
3788
3789     _G.stack_lat = 0;
3790
3791     /* add code for ISCRITICAL */
3792     if(IFFUNC_ISCRITICAL(sym->type)) {
3793       /* if critical function, turn on interrupts */
3794       
3795       /* TODO: add code here -- VR */
3796     }
3797     
3798 //    sym->regsUsed = _G.fregsUsed;
3799     
3800     /* now we need to restore the registers */
3801     /* if any registers used */
3802     if (sym->regsUsed) {
3803       int i;
3804
3805         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3806         /* restore registers used */
3807         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3808         for ( i = sym->regsUsed->size; i >= 0; i--) {
3809           if (bitVectBitValue(sym->regsUsed,i)) {
3810             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3811             _G.nRegsSaved--;
3812           }
3813         }
3814         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3815
3816     }
3817
3818     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3819           && sym->stack) {
3820       if (sym->stack == 1) {
3821         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3822         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3823       } else {
3824         // we have to add more than one...
3825         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3826         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3827         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3828         emitSKPNC;
3829         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3830         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3831         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3832       }
3833     }
3834
3835     if(strcmp(sym->name, "main")) {
3836       if(0 || !options.ommitFramePtr || sym->regsUsed) {
3837         /* restore stack frame */
3838         if(STACK_MODEL_LARGE)
3839           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3840         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3841       }
3842     }
3843
3844     _G.useWreg = 0;
3845
3846     if (IFFUNC_ISISR(sym->type)) {
3847       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3848       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3849       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3850       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3851
3852       if(!FUNC_ISSHADOWREGS(sym->type)) {
3853         /* do not restore interrupt vector for WREG,STATUS,BSR
3854          * for high priority interrupt, see genFunction */
3855         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3856         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3857         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3858       }
3859 //      _G.interruptvector = 0;         /* sanity check */
3860
3861
3862       /* if debug then send end of function */
3863 /*      if (options.debug && currFunc)  */
3864       if (currFunc) {
3865         debugFile->writeEndFunction (currFunc, ic, 1);
3866       }
3867         
3868       if(_G.usefastretfie)
3869         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3870       else
3871         pic16_emitpcodeNULLop(POC_RETFIE);
3872
3873       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3874       
3875       _G.usefastretfie = 0;
3876       return;
3877     }
3878
3879     if (IFFUNC_ISCRITICAL(sym->type)) {
3880       pic16_emitcode("setb","ea");
3881     }
3882
3883     /* if debug then send end of function */
3884     if (currFunc) {
3885       debugFile->writeEndFunction (currFunc, ic, 1);
3886     }
3887
3888     /* insert code to restore stack frame, if user enabled it
3889      * and function is not main() */
3890          
3891
3892     pic16_emitpcodeNULLop(POC_RETURN);
3893
3894     /* Mark the end of a function */
3895     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3896 }
3897
3898
3899 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3900 {
3901   unsigned long lit=1;
3902  
3903   // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3904   if(AOP_TYPE(op) == AOP_LIT) {
3905     if(!IS_FLOAT(operandType( op ))) {
3906       lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3907     } else {
3908       union {
3909         unsigned long lit_int;
3910         float lit_float;
3911       } info;
3912         
3913       /* take care if literal is a float */
3914       info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3915       lit = info.lit_int;
3916     }
3917   }
3918
3919   if(is_LitOp(op)) {
3920       if(lit == 0) {
3921         pic16_emitpcode(POC_CLRF, dest);
3922       } else {
3923         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3924         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3925       }
3926   } else {
3927     if(dest->type == PO_WREG && (offset == 0)) {
3928       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3929       return;
3930     }
3931     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3932   }
3933 }
3934
3935 /*-----------------------------------------------------------------*/
3936 /* genRet - generate code for return statement                     */
3937 /*-----------------------------------------------------------------*/
3938 static void genRet (iCode *ic)
3939 {
3940   int size;
3941   operand *left;
3942
3943     FENTRY;
3944         /* if we have no return value then
3945          * just generate the "ret" */
3946         
3947         if (!IC_LEFT(ic)) 
3948                 goto jumpret;       
3949     
3950         /* we have something to return then
3951          * move the return value into place */
3952         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3953         size = AOP_SIZE(IC_LEFT(ic));
3954
3955         if(size <= 4) {
3956                 if(size>3) {
3957                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3958 //                      pic16_emitpcode(POC_MOVFF,
3959 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3960                 }
3961                 if(size>2) {
3962                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3963 //                      pic16_emitpcode(POC_MOVFF,
3964 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3965                 }
3966                 if(size>1) {
3967                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3968 //                      pic16_emitpcode(POC_MOVFF,
3969 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3970                 }
3971
3972 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3973
3974                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3975 //              pic16_emitpcode(POC_MOVFF,
3976 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3977
3978         } else {
3979                 /* >32-bits, setup stack and FSR0 */
3980                 while (size--) {
3981 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3982 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3983
3984                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3985
3986 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3987                         GpsuedoStkPtr++;
3988                 }
3989                         
3990                 /* setup FSR0 */
3991                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3992                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3993
3994                 if(STACK_MODEL_LARGE) {
3995                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3996                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3997                 } else {
3998                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3999                 }
4000         }
4001                                 
4002 #if 0
4003         /* old code, left here for reference -- VR */    
4004         while (size--) {
4005           char *l ;
4006
4007                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4008                         /* #NOCHANGE */
4009                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4010                         pic16_emitpcomment("push %s",l);
4011                         pushed++;
4012                 } else {
4013                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4014                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4015                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4016                         
4017                         if (strcmp(fReturn[offset],l)) {
4018                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4019                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4020                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4021                                 } else {
4022                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4023                                 }
4024                                 
4025                                 if(size) {
4026                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4027                                 }
4028                                 offset++;
4029                         }
4030                 }
4031         }    
4032
4033         if (pushed) {
4034                 while(pushed) {
4035                         pushed--;
4036                         if (strcmp(fReturn[pushed],"a"))
4037                                 pic16_emitcode("pop",fReturn[pushed]);
4038                         else
4039                                 pic16_emitcode("pop","acc");
4040                 }
4041         }
4042 #endif
4043
4044
4045         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4046     
4047 jumpret:
4048         /* generate a jump to the return label
4049          * if the next is not the return statement */
4050         if (!(ic->next && ic->next->op == LABEL
4051                 && IC_LABEL(ic->next) == returnLabel)) {
4052         
4053                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4054                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4055         }
4056 }
4057
4058 /*-----------------------------------------------------------------*/
4059 /* genLabel - generates a label                                    */
4060 /*-----------------------------------------------------------------*/
4061 static void genLabel (iCode *ic)
4062 {
4063   FENTRY;
4064
4065   /* special case never generate */
4066   if (IC_LABEL(ic) == entryLabel)
4067     return ;
4068
4069   pic16_emitpLabel(IC_LABEL(ic)->key);
4070 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4071 }
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genGoto - generates a goto                                      */
4075 /*-----------------------------------------------------------------*/
4076 //tsd
4077 static void genGoto (iCode *ic)
4078 {
4079   FENTRY;
4080   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4081 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4082 }
4083
4084
4085 /*-----------------------------------------------------------------*/
4086 /* genMultbits :- multiplication of bits                           */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultbits (operand *left, 
4089                          operand *right, 
4090                          operand *result)
4091 {
4092   FENTRY;
4093
4094   if(!pic16_sameRegs(AOP(result),AOP(right)))
4095     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4096
4097   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4098   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4099   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4100
4101 }
4102
4103
4104 /*-----------------------------------------------------------------*/
4105 /* genMultOneByte : 8 bit multiplication & division                */
4106 /*-----------------------------------------------------------------*/
4107 static void genMultOneByte (operand *left,
4108                             operand *right,
4109                             operand *result)
4110 {
4111
4112   FENTRY;
4113   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4114   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4115
4116   /* (if two literals, the value is computed before) */
4117   /* if one literal, literal on the right */
4118   if (AOP_TYPE(left) == AOP_LIT){
4119     operand *t = right;
4120     right = left;
4121     left = t;
4122   }
4123
4124         /* size is already checked in genMult == 1 */
4125 //      size = AOP_SIZE(result);
4126
4127         if (AOP_TYPE(right) == AOP_LIT){
4128                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4129                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4130                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4131                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4132         } else {
4133                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4134                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4135                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4136                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4137         }
4138         
4139         pic16_genMult8X8_8 (left, right,result);
4140 }
4141
4142 /*-----------------------------------------------------------------*/
4143 /* genMultOneWord : 16 bit multiplication                          */
4144 /*-----------------------------------------------------------------*/
4145 static void genMultOneWord (operand *left,
4146                             operand *right,
4147                             operand *result)
4148 {
4149   FENTRY;
4150   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4151   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4152
4153   /* (if two literals, the value is computed before)
4154    * if one literal, literal on the right */
4155   if (AOP_TYPE(left) == AOP_LIT){
4156     operand *t = right;
4157     right = left;
4158     left = t;
4159   }
4160
4161   /* size is checked already == 2 */
4162 //  size = AOP_SIZE(result);
4163
4164   if (AOP_TYPE(right) == AOP_LIT) {
4165     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4166       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4167       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4168       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4169   } else {
4170     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4171       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4172       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4173       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4174   }
4175         
4176   pic16_genMult16X16_16(left, right,result);
4177 }
4178
4179 /*-----------------------------------------------------------------*/
4180 /* genMultOneLong : 32 bit multiplication                          */
4181 /*-----------------------------------------------------------------*/
4182 static void genMultOneLong (operand *left,
4183                             operand *right,
4184                             operand *result)
4185 {
4186   FENTRY;
4187   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4189
4190   /* (if two literals, the value is computed before)
4191    * if one literal, literal on the right */
4192   if (AOP_TYPE(left) == AOP_LIT){
4193     operand *t = right;
4194     right = left;
4195     left = t;
4196   }
4197
4198   /* size is checked already == 4 */
4199 //  size = AOP_SIZE(result);
4200
4201   if (AOP_TYPE(right) == AOP_LIT) {
4202     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4203         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4204         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4205         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4206   } else {
4207     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4208         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4209         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4210         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4211   }
4212         
4213   pic16_genMult32X32_32(left, right,result);
4214 }
4215
4216
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genMult - generates code for multiplication                     */
4220 /*-----------------------------------------------------------------*/
4221 static void genMult (iCode *ic)
4222 {
4223   operand *left = IC_LEFT(ic);
4224   operand *right = IC_RIGHT(ic);
4225   operand *result= IC_RESULT(ic);   
4226
4227     FENTRY;
4228         /* assign the amsops */
4229         pic16_aopOp (left,ic,FALSE);
4230         pic16_aopOp (right,ic,FALSE);
4231         pic16_aopOp (result,ic,TRUE);
4232
4233         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4234
4235         /* special cases first *
4236         * both are bits */
4237         if (AOP_TYPE(left) == AOP_CRY
4238                 && AOP_TYPE(right)== AOP_CRY) {
4239                 genMultbits(left,right,result);
4240           goto release ;
4241         }
4242
4243         /* if both are of size == 1 */
4244         if(AOP_SIZE(left) == 1
4245                 && AOP_SIZE(right) == 1) {
4246                 genMultOneByte(left,right,result);
4247           goto release ;
4248         }
4249
4250         /* if both are of size == 2 */
4251         if(AOP_SIZE(left) == 2
4252                 && AOP_SIZE(right) == 2) {
4253                 genMultOneWord(left, right, result);
4254           goto release;
4255         }
4256         
4257         /* if both are of size == 4 */
4258         if(AOP_SIZE(left) == 4
4259                 && AOP_SIZE(right) == 4) {
4260                 genMultOneLong(left, right, result);
4261           goto release;
4262         }
4263         
4264         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4265
4266
4267         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4268         /* should have been converted to function call */
4269         assert(0) ;
4270
4271 release :
4272         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4274         pic16_freeAsmop(result,NULL,ic,TRUE); 
4275 }
4276
4277 /*-----------------------------------------------------------------*/
4278 /* genDivbits :- division of bits                                  */
4279 /*-----------------------------------------------------------------*/
4280 static void genDivbits (operand *left, 
4281                         operand *right, 
4282                         operand *result)
4283 {
4284   char *l;
4285
4286     FENTRY;
4287     /* the result must be bit */    
4288     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4289     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4290
4291     MOVA(l);    
4292
4293     pic16_emitcode("div","ab");
4294     pic16_emitcode("rrc","a");
4295     pic16_aopPut(AOP(result),"c",0);
4296 }
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genDivOneByte : 8 bit division                                  */
4300 /*-----------------------------------------------------------------*/
4301 static void genDivOneByte (operand *left,
4302                            operand *right,
4303                            operand *result)
4304 {
4305   sym_link *opetype = operandType(result);
4306   char *l ;
4307   symbol *lbl ;
4308   int size,offset;
4309
4310         /* result = divident / divisor
4311          * - divident may be a register or a literal,
4312          * - divisor may be a register or a literal,
4313          * so there are 3 cases (literal / literal is optimized
4314          * by the front-end) to handle.
4315          * In addition we must handle signed and unsigned, which
4316          * result in 6 final different cases -- VR */
4317
4318     FENTRY;
4319     
4320     size = AOP_SIZE(result) - 1;
4321     offset = 1;
4322     /* signed or unsigned */
4323     if (SPEC_USIGN(opetype)) {
4324       pCodeOp *pct1,    /* count */
4325                 *pct2,  /* reste */
4326                 *pct3;  /* temp */
4327       symbol *label1, *label2, *label3;;
4328
4329
4330         /* unsigned is easy */
4331
4332         pct1 = pic16_popGetTempReg(1);
4333         pct2 = pic16_popGetTempReg(1);
4334         pct3 = pic16_popGetTempReg(1);
4335         
4336         label1 = newiTempLabel(NULL);
4337         label2 = newiTempLabel(NULL);
4338         label3 = newiTempLabel(NULL);
4339
4340         /* the following algorithm is extracted from divuint.c */
4341
4342         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4343         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4344         
4345         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4346
4347         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4348         
4349         pic16_emitpLabel(label1->key);
4350         
4351         emitCLRC;
4352         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4353
4354
4355         emitCLRC;
4356         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4357         
4358
4359         emitSKPNC;
4360         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4361         
4362         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4363         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4364         
4365         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4366         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4367         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4368         
4369         pic16_emitpLabel( label3->key );
4370         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4371         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4372         
4373         
4374
4375         pic16_emitpLabel(label2->key);
4376         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4377         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4378         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4379         
4380         /* result is in wreg */
4381         if(AOP_TYPE(result) != AOP_ACC)
4382                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4383
4384         pic16_popReleaseTempReg( pct3, 1);
4385         pic16_popReleaseTempReg( pct2, 1);
4386         pic16_popReleaseTempReg( pct1, 1);
4387
4388         return ;
4389     }
4390
4391     /* signed is a little bit more difficult */
4392
4393     /* save the signs of the operands */
4394     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4395     MOVA(l);    
4396     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4397     pic16_emitcode("push","acc"); /* save it on the stack */
4398
4399     /* now sign adjust for both left & right */
4400     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4401     MOVA(l);       
4402     lbl = newiTempLabel(NULL);
4403     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4404     pic16_emitcode("cpl","a");   
4405     pic16_emitcode("inc","a");
4406     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4407     pic16_emitcode("mov","b,a");
4408
4409     /* sign adjust left side */
4410     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4411     MOVA(l);
4412
4413     lbl = newiTempLabel(NULL);
4414     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4415     pic16_emitcode("cpl","a");
4416     pic16_emitcode("inc","a");
4417     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4418
4419     /* now the division */
4420     pic16_emitcode("div","ab");
4421     /* we are interested in the lower order
4422     only */
4423     pic16_emitcode("mov","b,a");
4424     lbl = newiTempLabel(NULL);
4425     pic16_emitcode("pop","acc");   
4426     /* if there was an over flow we don't 
4427     adjust the sign of the result */
4428     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4429     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4430     CLRC;
4431     pic16_emitcode("clr","a");
4432     pic16_emitcode("subb","a,b");
4433     pic16_emitcode("mov","b,a");
4434     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4435
4436     /* now we are done */
4437     pic16_aopPut(AOP(result),"b",0);
4438     if(size > 0){
4439         pic16_emitcode("mov","c,b.7");
4440         pic16_emitcode("subb","a,acc");   
4441     }
4442     while (size--)
4443         pic16_aopPut(AOP(result),"a",offset++);
4444
4445 }
4446
4447 /*-----------------------------------------------------------------*/
4448 /* genDiv - generates code for division                            */
4449 /*-----------------------------------------------------------------*/
4450 static void genDiv (iCode *ic)
4451 {
4452     operand *left = IC_LEFT(ic);
4453     operand *right = IC_RIGHT(ic);
4454     operand *result= IC_RESULT(ic);   
4455
4456
4457         /* Division is a very lengthy algorithm, so it is better
4458          * to call support routines than inlining algorithm.
4459          * Division functions written here just in case someone
4460          * wants to inline and not use the support libraries -- VR */
4461
4462     FENTRY;
4463     
4464     /* assign the amsops */
4465     pic16_aopOp (left,ic,FALSE);
4466     pic16_aopOp (right,ic,FALSE);
4467     pic16_aopOp (result,ic,TRUE);
4468
4469     /* special cases first */
4470     /* both are bits */
4471     if (AOP_TYPE(left) == AOP_CRY &&
4472         AOP_TYPE(right)== AOP_CRY) {
4473         genDivbits(left,right,result);
4474         goto release ;
4475     }
4476
4477     /* if both are of size == 1 */
4478     if (AOP_SIZE(left) == 1 &&
4479         AOP_SIZE(right) == 1 ) {
4480         genDivOneByte(left,right,result);
4481         goto release ;
4482     }
4483
4484     /* should have been converted to function call */
4485     assert(0);
4486 release :
4487     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489     pic16_freeAsmop(result,NULL,ic,TRUE); 
4490 }
4491
4492 /*-----------------------------------------------------------------*/
4493 /* genModbits :- modulus of bits                                   */
4494 /*-----------------------------------------------------------------*/
4495 static void genModbits (operand *left, 
4496                         operand *right, 
4497                         operand *result)
4498 {
4499   char *l;
4500
4501     FENTRY;  
4502     
4503     werror(W_POSSBUG2, __FILE__, __LINE__);
4504     /* the result must be bit */    
4505     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4506     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4507
4508     MOVA(l);       
4509
4510     pic16_emitcode("div","ab");
4511     pic16_emitcode("mov","a,b");
4512     pic16_emitcode("rrc","a");
4513     pic16_aopPut(AOP(result),"c",0);
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* genModOneByte : 8 bit modulus                                   */
4518 /*-----------------------------------------------------------------*/
4519 static void genModOneByte (operand *left,
4520                            operand *right,
4521                            operand *result)
4522 {
4523   sym_link *opetype = operandType(result);
4524   char *l ;
4525   symbol *lbl ;
4526
4527     FENTRY;
4528     werror(W_POSSBUG2, __FILE__, __LINE__);
4529
4530     /* signed or unsigned */
4531     if (SPEC_USIGN(opetype)) {
4532         /* unsigned is easy */
4533         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4534         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4535         MOVA(l);    
4536         pic16_emitcode("div","ab");
4537         pic16_aopPut(AOP(result),"b",0);
4538         return ;
4539     }
4540
4541     /* signed is a little bit more difficult */
4542
4543     /* save the signs of the operands */
4544     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4545     MOVA(l);
4546
4547     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4548     pic16_emitcode("push","acc"); /* save it on the stack */
4549
4550     /* now sign adjust for both left & right */
4551     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4552     MOVA(l);
4553
4554     lbl = newiTempLabel(NULL);
4555     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4556     pic16_emitcode("cpl","a");   
4557     pic16_emitcode("inc","a");
4558     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4559     pic16_emitcode("mov","b,a"); 
4560
4561     /* sign adjust left side */
4562     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4563     MOVA(l);
4564
4565     lbl = newiTempLabel(NULL);
4566     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4567     pic16_emitcode("cpl","a");   
4568     pic16_emitcode("inc","a");
4569     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4570
4571     /* now the multiplication */
4572     pic16_emitcode("div","ab");
4573     /* we are interested in the lower order
4574     only */
4575     lbl = newiTempLabel(NULL);
4576     pic16_emitcode("pop","acc");   
4577     /* if there was an over flow we don't 
4578     adjust the sign of the result */
4579     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4580     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4581     CLRC ;
4582     pic16_emitcode("clr","a");
4583     pic16_emitcode("subb","a,b");
4584     pic16_emitcode("mov","b,a");
4585     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4586
4587     /* now we are done */
4588     pic16_aopPut(AOP(result),"b",0);
4589
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genMod - generates code for division                            */
4594 /*-----------------------------------------------------------------*/
4595 static void genMod (iCode *ic)
4596 {
4597   operand *left = IC_LEFT(ic);
4598   operand *right = IC_RIGHT(ic);
4599   operand *result= IC_RESULT(ic);  
4600
4601     FENTRY;
4602     
4603     /* assign the amsops */
4604     pic16_aopOp (left,ic,FALSE);
4605     pic16_aopOp (right,ic,FALSE);
4606     pic16_aopOp (result,ic,TRUE);
4607
4608     /* special cases first */
4609     /* both are bits */
4610     if (AOP_TYPE(left) == AOP_CRY &&
4611         AOP_TYPE(right)== AOP_CRY) {
4612         genModbits(left,right,result);
4613         goto release ;
4614     }
4615
4616     /* if both are of size == 1 */
4617     if (AOP_SIZE(left) == 1 &&
4618         AOP_SIZE(right) == 1 ) {
4619         genModOneByte(left,right,result);
4620         goto release ;
4621     }
4622
4623     /* should have been converted to function call */
4624     assert(0);
4625
4626 release :
4627     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629     pic16_freeAsmop(result,NULL,ic,TRUE); 
4630 }
4631
4632 /*-----------------------------------------------------------------*/
4633 /* genIfxJump :- will create a jump depending on the ifx           */
4634 /*-----------------------------------------------------------------*/
4635 /*
4636   note: May need to add parameter to indicate when a variable is in bit space.
4637 */
4638 static void genIfxJump (iCode *ic, char *jval)
4639 {
4640   FENTRY;
4641   
4642     /* if true label then we jump if condition
4643     supplied is true */
4644     if ( IC_TRUE(ic) ) {
4645
4646         if(strcmp(jval,"a") == 0)
4647           emitSKPZ;
4648         else if (strcmp(jval,"c") == 0)
4649           emitSKPNC;
4650         else {
4651           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4652           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4653         }
4654
4655         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4656         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4657
4658     }
4659     else {
4660         /* false label is present */
4661         if(strcmp(jval,"a") == 0)
4662           emitSKPNZ;
4663         else if (strcmp(jval,"c") == 0)
4664           emitSKPC;
4665         else {
4666           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4667           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4668         }
4669
4670         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4671         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4672
4673     }
4674
4675
4676     /* mark the icode as generated */
4677     ic->generated = 1;
4678 }
4679
4680 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4681 {
4682   FENTRY;
4683   
4684     /* if true label then we jump if condition
4685     supplied is true */
4686     if ( IC_TRUE(ic) ) {
4687       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4688       pic16_emitpcode(POC_BTFSC, jop);
4689
4690       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4691       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4692
4693     } else {
4694       /* false label is present */
4695       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4696       pic16_emitpcode(POC_BTFSS, jop);
4697           
4698       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4699       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4700     }
4701
4702
4703     /* mark the icode as generated */
4704     ic->generated = 1;
4705 }
4706
4707 #if 0
4708 // not needed ATM
4709
4710 /*-----------------------------------------------------------------*/
4711 /* genSkip                                                         */
4712 /*-----------------------------------------------------------------*/
4713 static void genSkip(iCode *ifx,int status_bit)
4714 {
4715   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4716   if(!ifx)
4717     return;
4718
4719   if ( IC_TRUE(ifx) ) {
4720     switch(status_bit) {
4721     case 'z':
4722       emitSKPNZ;
4723       break;
4724
4725     case 'c':
4726       emitSKPNC;
4727       break;
4728
4729     case 'd':
4730       emitSKPDC;
4731       break;
4732
4733     }
4734
4735     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4736     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4737
4738   } else {
4739
4740     switch(status_bit) {
4741
4742     case 'z':
4743       emitSKPZ;
4744       break;
4745
4746     case 'c':
4747       emitSKPC;
4748       break;
4749
4750     case 'd':
4751       emitSKPDC;
4752       break;
4753     }
4754     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4755     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4756
4757   }
4758
4759 }
4760 #endif
4761
4762 /*-----------------------------------------------------------------*/
4763 /* genSkipc                                                        */
4764 /*-----------------------------------------------------------------*/
4765 static void genSkipc(resolvedIfx *rifx)
4766 {
4767   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4768   
4769   if(!rifx)
4770     return;
4771
4772   if(rifx->condition)
4773     emitSKPC;
4774   else
4775     emitSKPNC;
4776
4777   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4778   rifx->generated = 1;
4779 }
4780
4781 #if !(USE_SIMPLE_GENCMP)
4782 /*-----------------------------------------------------------------*/
4783 /* genSkipz2                                                       */
4784 /*-----------------------------------------------------------------*/
4785 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4786 {
4787   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4788   
4789   if(!rifx)
4790     return;
4791
4792   if( (rifx->condition ^ invert_condition) & 1)
4793     emitSKPZ;
4794   else
4795     emitSKPNZ;
4796
4797   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4798   rifx->generated = 1;
4799 }
4800 #endif
4801
4802 #if 0
4803 /*-----------------------------------------------------------------*/
4804 /* genSkipz                                                        */
4805 /*-----------------------------------------------------------------*/
4806 static void genSkipz(iCode *ifx, int condition)
4807 {
4808   if(!ifx)
4809     return;
4810
4811   if(condition)
4812     emitSKPNZ;
4813   else
4814     emitSKPZ;
4815
4816   if ( IC_TRUE(ifx) )
4817     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4818   else
4819     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4820
4821   if ( IC_TRUE(ifx) )
4822     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4823   else
4824     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4825
4826 }
4827 #endif
4828
4829 #if !(USE_SIMPLE_GENCMP)
4830 /*-----------------------------------------------------------------*/
4831 /* genSkipCond                                                     */
4832 /*-----------------------------------------------------------------*/
4833 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4834 {
4835   if(!rifx)
4836     return;
4837
4838   if(rifx->condition)
4839     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4840   else
4841     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4842
4843
4844   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4845   rifx->generated = 1;
4846 }
4847 #endif
4848
4849 #if 0
4850 /*-----------------------------------------------------------------*/
4851 /* genChkZeroes :- greater or less than comparison                 */
4852 /*     For each byte in a literal that is zero, inclusive or the   */
4853 /*     the corresponding byte in the operand with W                */
4854 /*     returns true if any of the bytes are zero                   */
4855 /*-----------------------------------------------------------------*/
4856 static int genChkZeroes(operand *op, int lit,  int size)
4857 {
4858
4859   int i;
4860   int flag =1;
4861
4862   while(size--) {
4863     i = (lit >> (size*8)) & 0xff;
4864
4865     if(i==0) {
4866       if(flag) 
4867         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4868       else
4869         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4870       flag = 0;
4871     }
4872   }
4873
4874   return (flag==0);
4875 }
4876 #endif
4877
4878 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4879 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4880 #endif
4881 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4882 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4883
4884 /*-----------------------------------------------------------------*/
4885 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4886 /*                  aop (if it's NOT a literal) or from lit (if    */
4887 /*                  aop is a literal)                              */
4888 /*-----------------------------------------------------------------*/
4889 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4890   if (aop->type == AOP_LIT) {
4891     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4892   } else {
4893     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4894   }
4895 }
4896
4897 /*-----------------------------------------------------------------*/
4898 /* genCmp :- greater or less than comparison                       */
4899 /*-----------------------------------------------------------------*/
4900
4901 #if USE_SIMPLE_GENCMP
4902
4903 /* genCmp performs a left < right comparison, stores
4904  * the outcome in result (if != NULL) and generates
4905  * control flow code for the ifx (if != NULL).
4906  *
4907  * This version leaves in sequences like
4908  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4909  * which should be optmized by the peephole
4910  * optimizer - RN 2005-01-01 */
4911 static void genCmp (operand *left,operand *right,
4912                     operand *result, iCode *ifx, int sign)
4913 {
4914   resolvedIfx rIfx;
4915   int size;
4916   int offs;
4917   symbol *templbl;
4918   operand *dummy;
4919   unsigned long lit;
4920   unsigned long mask;
4921   int performedLt;
4922
4923   FENTRY;
4924   
4925   assert (AOP_SIZE(left) == AOP_SIZE(right));
4926   assert (left && right);
4927
4928   size = AOP_SIZE(right) - 1;
4929   mask = (0x100UL << (size*8)) - 1;
4930   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4931   performedLt = 1;
4932   templbl = NULL;
4933   lit = 0;
4934   
4935   resolveIfx (&rIfx, ifx);
4936
4937   /**********************************************************************
4938    * handle bits - bit compares are promoted to int compares seemingly! *
4939    **********************************************************************/
4940 #if 0
4941   // THIS IS COMPLETELY UNTESTED!
4942   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4943     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4944     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4945     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4946
4947     emitSETC;
4948     // 1 < {0,1} is false --> clear C by skipping the next instruction
4949     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4950     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4951     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4952     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4953     emitCLRC; // only skipped for left=0 && right=1
4954
4955     goto correct_result_in_carry;
4956   } // if
4957 #endif
4958
4959   /*************************************************
4960    * make sure that left is register (or the like) *
4961    *************************************************/
4962   if (!isAOP_REGlike(left)) {
4963     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4964     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4965     #endif
4966     assert (isAOP_LIT(left));
4967     assert (isAOP_REGlike(right));
4968     // swap left and right
4969     // left < right <==> right > left <==> (right >= left + 1)
4970     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4971
4972     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4973       // MAXVALUE < right? always false
4974       if (performedLt) emitCLRC; else emitSETC;
4975       goto correct_result_in_carry;
4976     } // if
4977
4978     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4979     // that's we handled it above.
4980     lit++;
4981
4982     dummy = left;
4983     left = right;
4984     right = dummy;
4985
4986     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4987   } else if (isAOP_LIT(right)) {
4988     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4989   } // if
4990
4991   assert (isAOP_REGlike(left)); // left must be register or the like
4992   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4993
4994   /*************************************************
4995    * special cases go here                         *
4996    *************************************************/
4997
4998   if (isAOP_LIT(right)) {
4999     if (!sign) {
5000       // unsigned comparison to a literal
5001       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5002       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5003       #endif
5004       if (lit == 0) {
5005         // unsigned left < 0? always false
5006         if (performedLt) emitCLRC; else emitSETC;
5007         goto correct_result_in_carry;
5008       }
5009     } else {
5010       // signed comparison to a literal
5011       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5012       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5013       #endif
5014       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5015         // signed left < 0x80000000? always false
5016         if (performedLt) emitCLRC; else emitSETC;
5017         goto correct_result_in_carry;
5018       } else if (lit == 0) {
5019         // compare left < 0; set CARRY if SIGNBIT(left) is set
5020         if (performedLt) emitSETC; else emitCLRC;
5021         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5022         if (performedLt) emitCLRC; else emitSETC;
5023         goto correct_result_in_carry;
5024       }
5025     } // if (!sign)
5026   } // right is literal
5027
5028   /*************************************************
5029    * perform a general case comparison             *
5030    * make sure we get CARRY==1 <==> left >= right  *
5031    *************************************************/
5032   // compare most significant bytes
5033   //DEBUGpc ("comparing bytes at offset %d", size);
5034   if (!sign) {
5035     // unsigned comparison
5036     mov2w_regOrLit (AOP(right), lit, size);
5037     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5038   } else {
5039     // signed comparison
5040     // (add 2^n to both operands then perform an unsigned comparison)
5041     if (isAOP_LIT(right)) {
5042       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5043       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5044
5045       if (litbyte == 0x80) {
5046         // left >= 0x80 -- always true, but more bytes to come
5047         pic16_mov2w (AOP(left), size);
5048         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5049         emitSETC;
5050       } else {
5051         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5052         pic16_mov2w (AOP(left), size);
5053         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5054         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5055       } // if
5056     } else {
5057       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5058       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5059       pic16_mov2w (AOP(left), size);
5060       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5061       pic16_emitpcode (POC_MOVWF, pctemp);
5062       pic16_mov2w (AOP(right), size);
5063       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5064       pic16_emitpcode (POC_SUBFW, pctemp);
5065       //pic16_popReleaseTempReg(pctemp, 1);
5066     }
5067   } // if (!sign)
5068
5069   // compare remaining bytes (treat as unsigned case from above)
5070   templbl = newiTempLabel ( NULL );
5071   offs = size;
5072   while (offs--) {
5073     //DEBUGpc ("comparing bytes at offset %d", offs);
5074     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5075     mov2w_regOrLit (AOP(right), lit, offs);
5076     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5077   } // while (offs)
5078   pic16_emitpLabel (templbl->key);
5079   goto result_in_carry;
5080
5081 result_in_carry:
5082   
5083   /****************************************************
5084    * now CARRY contains the result of the comparison: *
5085    * SUBWF sets CARRY iff                             *
5086    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5087    * (F=left, W=right)
5088    ****************************************************/
5089
5090   if (performedLt) {
5091     if (result && AOP_TYPE(result) != AOP_CRY) {
5092       // value will be stored
5093       emitTOGC;
5094     } else {
5095       // value wil only be used in the following genSkipc()
5096       rIfx.condition ^= 1;
5097     }
5098   } // if
5099
5100 correct_result_in_carry:
5101
5102   // assign result to variable (if neccessary)
5103   if (result && AOP_TYPE(result) != AOP_CRY) {
5104     //DEBUGpc ("assign result");
5105     size = AOP_SIZE(result);
5106     while (size--) {
5107       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5108     } // while
5109     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5110   } // if (result)
5111
5112   // perform conditional jump
5113   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5114   if (ifx) {
5115     //DEBUGpc ("generate control flow");
5116     rIfx.condition ^= 1;
5117     genSkipc (&rIfx);
5118     ifx->generated = 1;
5119   } // if
5120 }
5121
5122 #elif 1
5123                 /* { */
5124       /* original code */
5125 static void genCmp (operand *left,operand *right,
5126                     operand *result, iCode *ifx, int sign)
5127 {
5128   int size; //, offset = 0 ;
5129   unsigned long lit = 0L,i = 0;
5130   resolvedIfx rFalseIfx;
5131   //  resolvedIfx rTrueIfx;
5132   symbol *truelbl;
5133   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5134 /*
5135   if(ifx) {
5136     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5137     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5138   }
5139 */
5140
5141   FENTRY;
5142   
5143   resolveIfx(&rFalseIfx,ifx);
5144   truelbl  = newiTempLabel(NULL);
5145   size = max(AOP_SIZE(left),AOP_SIZE(right));
5146
5147   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5148
5149 #define _swapp
5150
5151   /* if literal is on the right then swap with left */
5152   if ((AOP_TYPE(right) == AOP_LIT)) {
5153     operand *tmp = right ;
5154     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5155     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5156 #ifdef _swapp
5157
5158     lit = (lit - 1) & mask;
5159     right = left;
5160     left = tmp;
5161     rFalseIfx.condition ^= 1;
5162 #endif
5163
5164   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5165     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5166   }
5167
5168
5169   //if(IC_TRUE(ifx) == NULL)
5170   /* if left & right are bit variables */
5171   if (AOP_TYPE(left) == AOP_CRY &&
5172       AOP_TYPE(right) == AOP_CRY ) {
5173     assert (0 && "bit variables used in genCmp");
5174     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5175     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5176   } else {
5177     /* subtract right from left if at the
5178        end the carry flag is set then we know that
5179        left is greater than right */
5180
5181     symbol *lbl  = newiTempLabel(NULL);
5182
5183 #if 0
5184         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5185                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5186 #endif
5187
5188 #ifndef _swapp
5189     if(AOP_TYPE(right) == AOP_LIT) {
5190
5191       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5192
5193       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5194
5195       /* special cases */
5196
5197       if(lit == 0) {
5198
5199         if(sign != 0) 
5200           genSkipCond(&rFalseIfx,left,size-1,7);
5201         else 
5202           /* no need to compare to 0...*/
5203           /* NOTE: this is a de-generate compare that most certainly 
5204            *       creates some dead code. */
5205           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5206
5207         if(ifx) ifx->generated = 1;
5208         return;
5209
5210       }
5211       size--;
5212
5213       if(size == 0) {
5214         //i = (lit >> (size*8)) & 0xff;
5215         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5216         
5217         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5218
5219         i = ((0-lit) & 0xff);
5220         if(sign) {
5221           if( i == 0x81) { 
5222             /* lit is 0x7f, all signed chars are less than
5223              * this except for 0x7f itself */
5224             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5225             genSkipz2(&rFalseIfx,0);
5226           } else {
5227             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5228             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5229             genSkipc(&rFalseIfx);
5230           }
5231
5232         } else {
5233           if(lit == 1) {
5234             genSkipz2(&rFalseIfx,1);
5235           } else {
5236             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5237             genSkipc(&rFalseIfx);
5238           }
5239         }
5240
5241         if(ifx) ifx->generated = 1;
5242         return;
5243       }
5244
5245       /* chars are out of the way. now do ints and longs */
5246
5247
5248       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5249         
5250       /* special cases */
5251
5252       if(sign) {
5253
5254         if(lit == 0) {
5255           genSkipCond(&rFalseIfx,left,size,7);
5256           if(ifx) ifx->generated = 1;
5257           return;
5258         }
5259
5260         if(lit <0x100) {
5261           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5262
5263           //rFalseIfx.condition ^= 1;
5264           //genSkipCond(&rFalseIfx,left,size,7);
5265           //rFalseIfx.condition ^= 1;
5266
5267           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5268           if(rFalseIfx.condition)
5269             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5270           else
5271             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5272
5273           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5274           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5275           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5276
5277           while(size > 1)
5278             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5279
5280           if(rFalseIfx.condition) {
5281             emitSKPZ;
5282             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5283
5284           } else {
5285             emitSKPNZ;
5286           }
5287
5288           genSkipc(&rFalseIfx);
5289           pic16_emitpLabel(truelbl->key);
5290           if(ifx) ifx->generated = 1;
5291           return;
5292
5293         }
5294
5295         if(size == 1) {
5296
5297           if( (lit & 0xff) == 0) {
5298             /* lower byte is zero */
5299             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5300             i = ((lit >> 8) & 0xff) ^0x80;
5301             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5302             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5303             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5304             genSkipc(&rFalseIfx);
5305
5306
5307             if(ifx) ifx->generated = 1;
5308             return;
5309
5310           }
5311         } else {
5312           /* Special cases for signed longs */
5313           if( (lit & 0xffffff) == 0) {
5314             /* lower byte is zero */
5315             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5316             i = ((lit >> 8*3) & 0xff) ^0x80;
5317             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5318             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5319             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5320             genSkipc(&rFalseIfx);
5321
5322
5323             if(ifx) ifx->generated = 1;
5324             return;
5325
5326           }
5327
5328         }
5329
5330
5331         if(lit & (0x80 << (size*8))) {
5332           /* lit is negative */
5333           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334
5335           //genSkipCond(&rFalseIfx,left,size,7);
5336
5337           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5338
5339           if(rFalseIfx.condition)
5340             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5341           else
5342             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5343
5344
5345         } else {
5346           /* lit is positive */
5347           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5348           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5349           if(rFalseIfx.condition)
5350             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5351           else
5352             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5353
5354         }
5355
5356         /*
5357           This works, but is only good for ints.
5358           It also requires a "known zero" register.
5359           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5360           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5361           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5362           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5363           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5364           genSkipc(&rFalseIfx);
5365
5366           pic16_emitpLabel(truelbl->key);
5367           if(ifx) ifx->generated = 1;
5368           return;
5369         **/
5370           
5371         /* There are no more special cases, so perform a general compare */
5372   
5373         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5374         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5375
5376         while(size--) {
5377
5378           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5379           emitSKPNZ;
5380           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5381         }
5382         //rFalseIfx.condition ^= 1;
5383         genSkipc(&rFalseIfx);
5384
5385         pic16_emitpLabel(truelbl->key);
5386
5387         if(ifx) ifx->generated = 1;
5388         return;
5389
5390
5391       }
5392
5393
5394       /* sign is out of the way. So now do an unsigned compare */
5395       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5396
5397
5398       /* General case - compare to an unsigned literal on the right.*/
5399
5400       i = (lit >> (size*8)) & 0xff;
5401       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5402       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5403       while(size--) {
5404         i = (lit >> (size*8)) & 0xff;
5405
5406         if(i) {
5407           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5408           emitSKPNZ;
5409           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5410         } else {
5411           /* this byte of the lit is zero, 
5412            *if it's not the last then OR in the variable */
5413           if(size)
5414             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5415         }
5416       }
5417
5418
5419       pic16_emitpLabel(lbl->key);
5420 //      pic16_emitpLabel(truelbl->key);
5421       //if(emitFinalCheck)
5422       genSkipc(&rFalseIfx);
5423       if(sign)
5424         pic16_emitpLabel(truelbl->key);
5425
5426       if(ifx) ifx->generated = 1;
5427       return;
5428
5429
5430     }
5431 #endif  // _swapp
5432
5433     if(AOP_TYPE(left) == AOP_LIT) {
5434       //symbol *lbl = newiTempLabel(NULL);
5435
5436       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5437
5438
5439       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5440
5441       /* Special cases */
5442       if((lit == 0) && (sign == 0)){
5443
5444         size--;
5445         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5446         while(size) 
5447           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5448
5449         genSkipz2(&rFalseIfx,0);
5450         if(ifx) ifx->generated = 1;
5451         return;
5452       }
5453
5454       if(size==1) {
5455         /* Special cases */
5456         lit &= 0xff;
5457         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5458           /* degenerate compare can never be true */
5459           if(rFalseIfx.condition == 0)
5460             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5461
5462           if(ifx) ifx->generated = 1;
5463           return;
5464         }
5465
5466         if(sign) {
5467           /* signed comparisons to a literal byte */
5468
5469           int lp1 = (lit+1) & 0xff;
5470
5471           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5472           switch (lp1) {
5473           case 0:
5474             rFalseIfx.condition ^= 1;
5475             genSkipCond(&rFalseIfx,right,0,7);
5476             break;
5477           case 0x7f:
5478             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5479             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5480             genSkipz2(&rFalseIfx,1);
5481             break;
5482           default:
5483             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5484             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5485             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5486             rFalseIfx.condition ^= 1;
5487             genSkipc(&rFalseIfx);
5488             break;
5489           }
5490         } else {
5491           /* unsigned comparisons to a literal byte */
5492
5493           switch(lit & 0xff ) {
5494           case 0:
5495             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5496             genSkipz2(&rFalseIfx,0);
5497             break;
5498           case 0x7f:
5499             rFalseIfx.condition ^= 1;
5500             genSkipCond(&rFalseIfx,right,0,7);
5501             break;
5502
5503           default:
5504             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5505             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5506             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5507             rFalseIfx.condition ^= 1;
5508             if (AOP_TYPE(result) == AOP_CRY)
5509               genSkipc(&rFalseIfx);
5510             else {
5511               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5512               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5513             }         
5514             break;
5515           }
5516         }
5517
5518         if(ifx) ifx->generated = 1;
5519         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5520                 goto check_carry;
5521         return;
5522
5523       } else {
5524
5525         /* Size is greater than 1 */
5526
5527         if(sign) {
5528           int lp1 = lit+1;
5529
5530           size--;
5531
5532           if(lp1 == 0) {
5533             /* this means lit = 0xffffffff, or -1 */
5534
5535
5536             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5537             rFalseIfx.condition ^= 1;
5538             genSkipCond(&rFalseIfx,right,size,7);
5539             if(ifx) ifx->generated = 1;
5540
5541             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5542               goto check_carry;
5543
5544             return;
5545           }
5546
5547           if(lit == 0) {
5548             int s = size;
5549
5550             if(rFalseIfx.condition) {
5551               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5552               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5553             }
5554
5555             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5556             while(size--)
5557               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5558
5559
5560             emitSKPZ;
5561             if(rFalseIfx.condition) {
5562               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5563               pic16_emitpLabel(truelbl->key);
5564             }else {
5565               rFalseIfx.condition ^= 1;
5566               genSkipCond(&rFalseIfx,right,s,7);
5567             }
5568
5569             if(ifx) ifx->generated = 1;
5570
5571             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5572               goto check_carry;
5573
5574             return;
5575           }
5576
5577           if((size == 1) &&  (0 == (lp1&0xff))) {
5578             /* lower byte of signed word is zero */
5579             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5580             i = ((lp1 >> 8) & 0xff) ^0x80;
5581             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5582             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5583             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5584
5585             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5586               emitTOGC;
5587               if(ifx) ifx->generated = 1;
5588               goto check_carry;
5589             } else {
5590               rFalseIfx.condition ^= 1;
5591               genSkipc(&rFalseIfx);
5592               if(ifx) ifx->generated = 1;
5593             }
5594
5595             return;
5596           }
5597
5598           if(lit & (0x80 << (size*8))) {
5599             /* Lit is less than zero */
5600             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5601             //rFalseIfx.condition ^= 1;
5602             //genSkipCond(&rFalseIfx,left,size,7);
5603             //rFalseIfx.condition ^= 1;
5604             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5605             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5606
5607             if(rFalseIfx.condition)
5608               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5609             else
5610               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5611
5612
5613           } else {
5614             /* Lit is greater than or equal to zero */
5615             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5616             //rFalseIfx.condition ^= 1;
5617             //genSkipCond(&rFalseIfx,right,size,7);
5618             //rFalseIfx.condition ^= 1;
5619
5620             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5621             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5622
5623             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624             if(rFalseIfx.condition)
5625               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5626             else
5627               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5628
5629           }
5630
5631           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5632           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5633
5634           while(size--) {
5635
5636             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5637             emitSKPNZ;
5638             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5639           }
5640           rFalseIfx.condition ^= 1;
5641           //rFalseIfx.condition = 1;
5642           genSkipc(&rFalseIfx);
5643
5644           pic16_emitpLabel(truelbl->key);
5645
5646           if(ifx) ifx->generated = 1;
5647
5648
5649           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5650             goto check_carry;
5651
5652           return;
5653           // end of if (sign)
5654         } else {
5655
5656           /* compare word or long to an unsigned literal on the right.*/
5657
5658
5659           size--;
5660           if(lit < 0xff) {
5661             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5662             switch (lit) {
5663             case 0:
5664               break; /* handled above */
5665 /*
5666             case 0xff:
5667               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5668               while(size--)
5669                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5670               genSkipz2(&rFalseIfx,0);
5671               break;
5672 */
5673             default:
5674               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5675               while(--size)
5676                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5677
5678               emitSKPZ;
5679               if(rFalseIfx.condition)
5680                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5681               else
5682                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5683
5684
5685               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5686               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5687
5688               rFalseIfx.condition ^= 1;
5689               genSkipc(&rFalseIfx);
5690             }
5691
5692             pic16_emitpLabel(truelbl->key);
5693
5694             if(ifx) ifx->generated = 1;
5695
5696             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5697               goto check_carry;
5698
5699             return;
5700           }
5701
5702
5703           lit++;
5704           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5705           i = (lit >> (size*8)) & 0xff;
5706
5707           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5708           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5709
5710           while(size--) {
5711             i = (lit >> (size*8)) & 0xff;
5712
5713             if(i) {
5714               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5715               emitSKPNZ;
5716               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5717             } else {
5718               /* this byte of the lit is zero, 
5719                * if it's not the last then OR in the variable */
5720               if(size)
5721                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5722             }
5723           }
5724
5725
5726           pic16_emitpLabel(lbl->key);
5727
5728           rFalseIfx.condition ^= 1;
5729
5730           genSkipc(&rFalseIfx);
5731         }
5732
5733         if(sign)
5734           pic16_emitpLabel(truelbl->key);
5735         if(ifx) ifx->generated = 1;
5736
5737             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5738               goto check_carry;
5739
5740         return;
5741       }
5742     }
5743     /* Compare two variables */
5744
5745     DEBUGpic16_emitcode(";sign","%d",sign);
5746
5747     size--;
5748     if(sign) {
5749       /* Sigh. thus sucks... */
5750       if(size) {
5751         pCodeOp *pctemp;
5752         
5753         pctemp = pic16_popGetTempReg(1);
5754         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5755         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5756         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5757         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5758         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5759         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5760         pic16_popReleaseTempReg(pctemp, 1);
5761       } else {
5762         /* Signed char comparison */
5763         /* Special thanks to Nikolai Golovchenko for this snippet */
5764         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5765         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5766         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5767         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5768         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5769         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5770
5771         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5772         genSkipc(&rFalseIfx);
5773           
5774         if(ifx) ifx->generated = 1;
5775
5776             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5777               goto check_carry;
5778
5779         return;
5780       }
5781
5782     } else {
5783
5784       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5785       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5786     }
5787
5788
5789     /* The rest of the bytes of a multi-byte compare */
5790     while (size) {
5791
5792       emitSKPZ;
5793       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5794       size--;
5795
5796       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5797       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5798
5799
5800     }
5801
5802     pic16_emitpLabel(lbl->key);
5803
5804     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5805     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5806         (AOP_TYPE(result) == AOP_REG)) {
5807       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5808       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5809     } else {
5810       genSkipc(&rFalseIfx);
5811     }         
5812     //genSkipc(&rFalseIfx);
5813     if(ifx) ifx->generated = 1;
5814
5815
5816             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5817               goto check_carry;
5818
5819     return;
5820
5821   }
5822
5823 check_carry:
5824   if ((AOP_TYPE(result) != AOP_CRY) 
5825         && AOP_SIZE(result)) {
5826     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5827
5828     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5829
5830     pic16_outBitC(result);
5831   } else {
5832     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5833     /* if the result is used in the next
5834        ifx conditional branch then generate
5835        code a little differently */
5836     if (ifx )
5837       genIfxJump (ifx,"c");
5838     else
5839       pic16_outBitC(result);
5840     /* leave the result in acc */
5841   }
5842
5843 }
5844
5845 #else   /* old version of genCmp() */   /* } else { */
5846
5847 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5848 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5849         operand *result, int offset, int invert_op)
5850 {
5851   /* add code here */
5852   
5853   /* check condition, > or < ?? */
5854   if(rIfx->condition != 0)invert_op ^= 1;
5855   
5856   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5857
5858   if(!ifx)invert_op ^= 1;
5859
5860   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5861       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5862   
5863   /* do selection */
5864   if(!invert_op)return POC_CPFSGT;
5865   else return POC_CPFSLT;
5866 }
5867
5868 static int compareAopfirstpass=1;
5869
5870 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5871             operand *oper, int offset, operand *result,
5872             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5873             symbol *tlbl)
5874 {
5875   int op;
5876   symbol *truelbl;
5877
5878   /* invert if there is a result to be loaded, in order to fit,
5879    * SETC/CLRC sequence */
5880   if(AOP_SIZE(result))invert_op ^= 1;
5881
5882 //  if(sign && !offset)invert_op ^= 1;
5883   
5884 //  if(sign)invert_op ^= 1;
5885   
5886   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5887
5888   if(AOP_SIZE(result) && compareAopfirstpass) {
5889     if(!ifx) {
5890       if(pcop2)
5891         pic16_emitpcode(POC_SETF, pcop2);
5892       else
5893         emitSETC;
5894     } else {
5895       if(pcop2)
5896         pic16_emitpcode(POC_CLRF, pcop2);
5897       else
5898         emitCLRC;
5899     }
5900   }
5901
5902   compareAopfirstpass = 0;
5903
5904       /* there is a bug when comparing operands with size > 1,
5905        * because higher bytes can be equal and test should be performed
5906        * to the next lower byte, current algorithm, considers operands
5907        * inequal in these cases! -- VR 20041107 */
5908
5909     
5910   if(pcop)
5911     pic16_emitpcode(op, pcop);
5912   else
5913     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5914
5915
5916   if((!sign || !offset) && AOP_SIZE(result)) {
5917     if(!ifx) {
5918       if(pcop2)
5919         pic16_emitpcode(POC_CLRF, pcop2);
5920         else
5921         emitCLRC;
5922     } else {
5923       if(pcop2)
5924         pic16_emitpcode(POC_SETF, pcop2);
5925       else
5926         emitSETC;
5927     }
5928     
5929     /* don't emit final branch (offset == 0) */
5930     if(offset) {
5931
5932       if(pcop2)
5933         pic16_emitpcode(POC_RRCF, pcop2);
5934
5935       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5936     }
5937   } else {
5938     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5939       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5940             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5941
5942       truelbl = newiTempLabel( NULL );
5943       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5944       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5945         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5946       else
5947         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5948       pic16_emitpLabel(truelbl->key);
5949     } else {
5950       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5951     }
5952   }
5953 }
5954
5955
5956   
5957
5958 #if 1   /* { */
5959 static void genCmp (operand *left, operand *right,
5960                     operand *result, iCode *ifx, int sign)
5961 {
5962   int size, cmpop=1;
5963   long lit = 0L;
5964   resolvedIfx rFalseIfx;
5965   symbol *falselbl, *tlbl;
5966
5967     FENTRY;
5968     
5969     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5970
5971     resolveIfx(&rFalseIfx, ifx);
5972     size = max(AOP_SIZE(left), AOP_SIZE(right));
5973     
5974     /* if left & right are bit variables */
5975     if(AOP_TYPE(left) == AOP_CRY
5976       && AOP_TYPE(right) == AOP_CRY ) {
5977
5978         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5979         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5980         
5981         werror(W_POSSBUG2, __FILE__, __LINE__);
5982         exit(-1);
5983     }
5984     
5985     /* if literal is on the right then swap with left */
5986     if((AOP_TYPE(right) == AOP_LIT)) {
5987       operand *tmp = right ;
5988 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5989
5990         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5991
5992 //      lit = (lit - 1) & mask;
5993         right = left;
5994         left = tmp;
5995         rFalseIfx.condition ^= 1;               /* reverse compare */
5996     } else
5997     if ((AOP_TYPE(left) == AOP_LIT)) {
5998       /* float compares are handled by support functions */
5999       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6000     }
6001
6002     /* actual comparing algorithm */
6003 //    size = AOP_SIZE( right );
6004
6005     falselbl = newiTempLabel( NULL );
6006     if(AOP_TYPE(left) == AOP_LIT) {
6007       /* compare to literal */
6008       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6009       
6010       if(sign) {
6011         pCodeOp *pct, *pct2;
6012         symbol *tlbl1;
6013
6014         /* signed compare */
6015         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6016
6017         pct = pic16_popCopyReg(&pic16_pc_prodl);
6018         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6019         tlbl = newiTempLabel( NULL );
6020         
6021         /* first compare signs:
6022          *  a. if both are positive, compare just like unsigned
6023          *  b. if both are negative, invert cmpop, compare just like unsigned
6024          *  c. if different signs, determine the result directly */
6025
6026         size--;
6027
6028 #if 1
6029         /* { */
6030         tlbl1 = newiTempLabel( NULL );
6031 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6032
6033         if(lit > 0) {
6034
6035           /* literal is zero or positive:
6036            *  a. if carry is zero, too, continue compare,
6037            *  b. if carry is set, then continue depending on cmpop ^ condition:
6038            *    1. '<' return false (literal < variable),
6039            *    2. '>' return true (literal > variable) */
6040 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6041           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6042           
6043           
6044           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6045           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6046         } else 
6047         if(lit < 0) {
6048           
6049           /* literal is negative:
6050            *  a. if carry is set, too, continue compare,
6051            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6052            *    1. '<' return true (literal < variable),
6053            *    2. '>' return false (literal > variable) */
6054 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6055           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6056           
6057           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6058           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6059         }
6060 #if 1
6061         else {
6062           /* lit == 0 */
6063           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6064           
6065           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6066           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6067         }
6068 #endif
6069         
6070         
6071         pic16_emitpLabel( tlbl1->key );
6072 #endif  /* } */
6073
6074         compareAopfirstpass=1;
6075 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6076 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6077 //        pic16_emitpcode(POC_MOVWF, pct);
6078
6079 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6080         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6081 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6082         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6083
6084         /* generic case */        
6085           while( size-- ) {
6086 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6087 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6088 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6089 //            pic16_emitpcode(POC_MOVWF, pct);
6090
6091 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6092             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6093             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6094 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6095 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6096           }
6097 //        }
6098         
6099         if(ifx)ifx->generated = 1;
6100
6101         if(AOP_SIZE(result)) {
6102           pic16_emitpLabel(tlbl->key);
6103           pic16_emitpLabel(falselbl->key);
6104           pic16_outBitOp( result, pct2 );
6105         } else {
6106           pic16_emitpLabel(tlbl->key);
6107         }
6108       } else {
6109
6110
6111         /* unsigned compare */      
6112         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6113     
6114         compareAopfirstpass=1;
6115         while(size--) {
6116           
6117           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6118           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6119
6120         }
6121
6122         if(ifx)ifx->generated = 1;
6123
6124
6125         if(AOP_SIZE(result)) {
6126           pic16_emitpLabel(falselbl->key);
6127           pic16_outBitC( result );
6128         }
6129
6130       }
6131     } else {
6132       /* compare registers */
6133       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6134
6135
6136       if(sign) {
6137         pCodeOp *pct, *pct2;
6138         
6139         /* signed compare */
6140         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6141
6142         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6143         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6144         tlbl = newiTempLabel( NULL );
6145         
6146         compareAopfirstpass=1;
6147
6148         size--;
6149         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6150 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6151         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6152         pic16_emitpcode(POC_MOVWF, pct);
6153
6154         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6155 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6156         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6157
6158         /* WREG already holds left + 0x80 */
6159         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6160         
6161         while( size-- ) {
6162           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6163 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6164           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6165           pic16_emitpcode(POC_MOVWF, pct);
6166                 
6167           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6168 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6169           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6170
6171           /* WREG already holds left + 0x80 */
6172           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6173 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6174         }
6175         
6176         if(ifx)ifx->generated = 1;
6177
6178         if(AOP_SIZE(result)) {
6179           pic16_emitpLabel(tlbl->key);
6180           pic16_emitpLabel(falselbl->key);
6181           pic16_outBitOp( result, pct2 );
6182         } else {
6183           pic16_emitpLabel(tlbl->key);
6184         }
6185
6186       } else {
6187         /* unsigned compare */      
6188         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6189
6190         compareAopfirstpass=1;
6191         while(size--) {
6192           
6193           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6194           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6195
6196         }
6197
6198         if(ifx)ifx->generated = 1;
6199         if(AOP_SIZE(result)) {
6200
6201           pic16_emitpLabel(falselbl->key);
6202           pic16_outBitC( result );
6203         }
6204
6205       }
6206     }
6207 }
6208
6209 #else    /* } else { */
6210
6211 /* new version of genCmp -- VR 20041012 */
6212 static void genCmp (operand *left,operand *right,
6213                     operand *result, iCode *ifx, int sign)
6214 {
6215   int size; //, offset = 0 ;
6216   unsigned long lit = 0L,i = 0;
6217   resolvedIfx rFalseIfx;
6218   int willCheckCarry=0;
6219   //  resolvedIfx rTrueIfx;
6220   symbol *truelbl;
6221
6222     FENTRY;
6223   
6224   /* General concept:
6225    * subtract right from left if at the end the carry flag is set then we
6226    * know that left is greater than right */
6227             
6228   resolveIfx(&rFalseIfx,ifx);
6229   truelbl  = newiTempLabel(NULL);
6230   size = max(AOP_SIZE(left),AOP_SIZE(right));
6231
6232   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6233
6234   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6235    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6236   
6237
6238   /* if literal is on the right then swap with left */
6239   if ((AOP_TYPE(right) == AOP_LIT)) {
6240     operand *tmp = right ;
6241     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6242
6243       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6244
6245 //      lit = (lit - 1) & mask;
6246       right = left;
6247       left = tmp;
6248       rFalseIfx.condition ^= 1;         /* reverse compare */
6249   } else
6250   if ((AOP_TYPE(left) == AOP_LIT)) {
6251     /* float compares are handled by support functions */
6252     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6253   }
6254
6255
6256   //if(IC_TRUE(ifx) == NULL)
6257   /* if left & right are bit variables */
6258   if (AOP_TYPE(left) == AOP_CRY &&
6259       AOP_TYPE(right) == AOP_CRY ) {
6260
6261     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6262     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6263
6264   } else {
6265     symbol *lbl  = newiTempLabel(NULL);
6266
6267     if(AOP_TYPE(left) == AOP_LIT) {
6268       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6269
6270       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6271         willCheckCarry = 1;
6272       else willCheckCarry = 0;
6273
6274       /* Special cases */
6275       if((lit == 0) && (sign == 0)) {
6276         /* unsigned compare to 0 */
6277         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6278         
6279         size--;
6280         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6281         while(size) 
6282           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6283
6284         genSkipz2(&rFalseIfx,0);
6285         if(ifx)ifx->generated = 1;
6286         return;
6287       }
6288
6289       if(size==1) {
6290         /* Special cases */
6291         lit &= 0xff;
6292         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6293           /* degenerate compare can never be true */
6294           if(rFalseIfx.condition == 0)
6295             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6296
6297           if(ifx) ifx->generated = 1;
6298           return;
6299         }
6300
6301         if(sign) {
6302           /* signed comparisons to a literal byte */
6303           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6304
6305           int lp1 = (lit+1) & 0xff;
6306
6307           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6308           switch (lp1) {
6309           case 0:
6310             rFalseIfx.condition ^= 1;
6311             genSkipCond(&rFalseIfx,right,0,7);
6312             break;
6313           case 0x7f:
6314             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6315             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6316             genSkipz2(&rFalseIfx,1);
6317             break;
6318           default:
6319             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6320             
6321             if(rFalseIfx.condition)
6322               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6323             else
6324               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6325
6326             if(willCheckCarry) {
6327               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6328               else { emitSETC; emitCLRC; }
6329               
6330             } else {
6331               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6332             }              
6333                       
6334 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6335             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6336             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6337             rFalseIfx.condition ^= 1;
6338             genSkipc(&rFalseIfx);
6339 */
6340             break;
6341           }
6342         } else {
6343           /* unsigned comparisons to a literal byte */
6344           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6345
6346           switch(lit & 0xff ) {
6347                           /* special cases */
6348           case 0:
6349             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6350             genSkipz2(&rFalseIfx,0);
6351             break;
6352           case 0x7f:
6353             rFalseIfx.condition ^= 1;
6354             genSkipCond(&rFalseIfx,right,0,7);
6355             break;
6356           default:
6357             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6358             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6359             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6360             rFalseIfx.condition ^= 1;
6361             if (AOP_TYPE(result) == AOP_CRY)
6362               genSkipc(&rFalseIfx);
6363             else {
6364               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6365               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6366             }         
6367             break;
6368           }
6369         }
6370
6371         if(ifx) ifx->generated = 1;
6372         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6373                 goto check_carry;
6374         return;
6375
6376       } else {
6377
6378         /* Size is greater than 1 */
6379
6380         if(sign) {
6381           int lp1 = lit+1;
6382
6383           size--;
6384
6385           if(lp1 == 0) {
6386             /* this means lit = 0xffffffff, or -1 */
6387
6388
6389             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6390             rFalseIfx.condition ^= 1;
6391             genSkipCond(&rFalseIfx,right,size,7);
6392             if(ifx) ifx->generated = 1;
6393             return;
6394           }
6395
6396           if(lit == 0) {
6397             int s = size;
6398
6399             if(rFalseIfx.condition) {
6400               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6401               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6402             }
6403
6404             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6405             while(size--)
6406               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6407
6408
6409             emitSKPZ;
6410             if(rFalseIfx.condition) {
6411               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6412               pic16_emitpLabel(truelbl->key);
6413             }else {
6414               rFalseIfx.condition ^= 1;
6415               genSkipCond(&rFalseIfx,right,s,7);
6416             }
6417
6418             if(ifx) ifx->generated = 1;
6419             return;
6420           }
6421
6422           if((size == 1) &&  (0 == (lp1&0xff))) {
6423             /* lower byte of signed word is zero */
6424             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6425             i = ((lp1 >> 8) & 0xff) ^0x80;
6426             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6427             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6428             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6429             rFalseIfx.condition ^= 1;
6430             genSkipc(&rFalseIfx);
6431
6432
6433             if(ifx) ifx->generated = 1;
6434             return;
6435           }
6436
6437           if(lit & (0x80 << (size*8))) {
6438             /* Lit is less than zero */
6439             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6440             //rFalseIfx.condition ^= 1;
6441             //genSkipCond(&rFalseIfx,left,size,7);
6442             //rFalseIfx.condition ^= 1;
6443             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6444             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6445
6446             if(rFalseIfx.condition)
6447               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6448             else
6449               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6450
6451
6452           } else {
6453             /* Lit is greater than or equal to zero */
6454             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6455             //rFalseIfx.condition ^= 1;
6456             //genSkipCond(&rFalseIfx,right,size,7);
6457             //rFalseIfx.condition ^= 1;
6458
6459             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6460             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6461
6462             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6463             if(rFalseIfx.condition)
6464               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6465             else
6466               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6467
6468           }
6469
6470
6471           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6472           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6473
6474           while(size--) {
6475
6476             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6477             emitSKPNZ;
6478             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6479           }
6480           rFalseIfx.condition ^= 1;
6481           //rFalseIfx.condition = 1;
6482           genSkipc(&rFalseIfx);
6483
6484           pic16_emitpLabel(truelbl->key);
6485
6486           if(ifx) ifx->generated = 1;
6487           return;
6488           // end of if (sign)
6489         } else {
6490
6491           /* compare word or long to an unsigned literal on the right.*/
6492
6493
6494           size--;
6495           if(lit < 0xff) {
6496             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6497             switch (lit) {
6498             case 0:
6499               break; /* handled above */
6500 /*
6501             case 0xff:
6502               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6503               while(size--)
6504                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6505               genSkipz2(&rFalseIfx,0);
6506               break;
6507 */
6508             default:
6509               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6510               while(--size)
6511                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6512
6513               emitSKPZ;
6514               if(rFalseIfx.condition)
6515                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6516               else
6517                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6518
6519
6520               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6521               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6522
6523               rFalseIfx.condition ^= 1;
6524               genSkipc(&rFalseIfx);
6525             }
6526
6527             pic16_emitpLabel(truelbl->key);
6528
6529             if(ifx) ifx->generated = 1;
6530             return;
6531           }
6532
6533
6534           lit++;
6535           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6536           i = (lit >> (size*8)) & 0xff;
6537
6538           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6539           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6540
6541           while(size--) {
6542             i = (lit >> (size*8)) & 0xff;
6543
6544             if(i) {
6545               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6546               emitSKPNZ;
6547               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6548             } else {
6549               /* this byte of the lit is zero, 
6550                * if it's not the last then OR in the variable */
6551               if(size)
6552                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6553             }
6554           }
6555
6556
6557           pic16_emitpLabel(lbl->key);
6558
6559           rFalseIfx.condition ^= 1;
6560
6561           genSkipc(&rFalseIfx);
6562         }
6563
6564         if(sign)
6565           pic16_emitpLabel(truelbl->key);
6566         if(ifx) ifx->generated = 1;
6567         return;
6568       }
6569     }
6570     /* Compare two variables */
6571
6572     DEBUGpic16_emitcode(";sign","%d",sign);
6573
6574     size--;
6575     if(sign) {
6576       /* Sigh. thus sucks... */
6577       if(size) {
6578         pCodeOp *pctemp;
6579         
6580         pctemp = pic16_popGetTempReg(1);
6581         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6582         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6583         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6584         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6585         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6586         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6587         pic16_popReleaseTempReg(pctemp, 1);
6588       } else {
6589         /* Signed char comparison */
6590         /* Special thanks to Nikolai Golovchenko for this snippet */
6591         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6592         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6593         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6594         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6595         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6596         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6597
6598         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6599         genSkipc(&rFalseIfx);
6600           
6601         if(ifx) ifx->generated = 1;
6602         return;
6603       }
6604
6605     } else {
6606
6607       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6608       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6609     }
6610
6611
6612     /* The rest of the bytes of a multi-byte compare */
6613     while (size) {
6614
6615       emitSKPZ;
6616       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6617       size--;
6618
6619       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6620       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6621
6622
6623     }
6624
6625     pic16_emitpLabel(lbl->key);
6626
6627     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6629         (AOP_TYPE(result) == AOP_REG)) {
6630       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6631       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6632     } else {
6633       genSkipc(&rFalseIfx);
6634     }         
6635     //genSkipc(&rFalseIfx);
6636     if(ifx) ifx->generated = 1;
6637
6638     return;
6639
6640   }
6641
6642 check_carry:
6643   if ((AOP_TYPE(result) != AOP_CRY) 
6644         && AOP_SIZE(result)) {
6645     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6646
6647     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6648
6649     pic16_outBitC(result);
6650   } else {
6651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6652     /* if the result is used in the next
6653        ifx conditional branch then generate
6654        code a little differently */
6655     if (ifx )
6656       genIfxJump (ifx,"c");
6657     else
6658       pic16_outBitC(result);
6659     /* leave the result in acc */
6660   }
6661
6662 }
6663 #endif  /* } */
6664
6665
6666 #endif  /* } */
6667
6668
6669
6670 /*-----------------------------------------------------------------*/
6671 /* genCmpGt :- greater than comparison                             */
6672 /*-----------------------------------------------------------------*/
6673 static void genCmpGt (iCode *ic, iCode *ifx)
6674 {
6675   operand *left, *right, *result;
6676   sym_link *letype , *retype;
6677   int sign ;
6678
6679     FENTRY;
6680     
6681     left = IC_LEFT(ic);
6682     right= IC_RIGHT(ic);
6683     result = IC_RESULT(ic);
6684
6685     letype = getSpec(operandType(left));
6686     retype =getSpec(operandType(right));
6687     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6688     /* assign the amsops */
6689     pic16_aopOp (left,ic,FALSE);
6690     pic16_aopOp (right,ic,FALSE);
6691     pic16_aopOp (result,ic,TRUE);
6692
6693     genCmp(right, left, result, ifx, sign);
6694
6695     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6696     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6697     pic16_freeAsmop(result,NULL,ic,TRUE); 
6698 }
6699
6700 /*-----------------------------------------------------------------*/
6701 /* genCmpLt - less than comparisons                                */
6702 /*-----------------------------------------------------------------*/
6703 static void genCmpLt (iCode *ic, iCode *ifx)
6704 {
6705   operand *left, *right, *result;
6706   sym_link *letype , *retype;
6707   int sign ;
6708
6709     FENTRY;
6710
6711     left = IC_LEFT(ic);
6712     right= IC_RIGHT(ic);
6713     result = IC_RESULT(ic);
6714
6715     letype = getSpec(operandType(left));
6716     retype =getSpec(operandType(right));
6717     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6718
6719     /* assign the amsops */
6720     pic16_aopOp (left,ic,FALSE);
6721     pic16_aopOp (right,ic,FALSE);
6722     pic16_aopOp (result,ic,TRUE);
6723
6724     genCmp(left, right, result, ifx, sign);
6725
6726     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6727     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6728     pic16_freeAsmop(result,NULL,ic,TRUE); 
6729 }
6730
6731 #if 0
6732 // not needed ATM
6733 // FIXME reenable literal optimisation when the pic16 port is stable
6734
6735 /*-----------------------------------------------------------------*/
6736 /* genc16bit2lit - compare a 16 bit value to a literal             */
6737 /*-----------------------------------------------------------------*/
6738 static void genc16bit2lit(operand *op, int lit, int offset)
6739 {
6740   int i;
6741
6742   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6743   if( (lit&0xff) == 0) 
6744     i=1;
6745   else
6746     i=0;
6747
6748   switch( BYTEofLONG(lit,i)) { 
6749   case 0:
6750     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6751     break;
6752   case 1:
6753     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6754     break;
6755   case 0xff:
6756     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6757     break;
6758   default:
6759     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6760     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6761   }
6762
6763   i ^= 1;
6764
6765   switch( BYTEofLONG(lit,i)) { 
6766   case 0:
6767     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6768     break;
6769   case 1:
6770     emitSKPNZ;
6771     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6772     break;
6773   case 0xff:
6774     emitSKPNZ;
6775     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6776     break;
6777   default:
6778     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6779     emitSKPNZ;
6780     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6781
6782   }
6783
6784 }
6785 #endif
6786
6787 #if 0
6788 // not needed ATM
6789 /*-----------------------------------------------------------------*/
6790 /* gencjneshort - compare and jump if not equal                    */
6791 /*-----------------------------------------------------------------*/
6792 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6793 {
6794   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6795   int offset = 0;
6796   int res_offset = 0;  /* the result may be a different size then left or right */
6797   int res_size = AOP_SIZE(result);
6798   resolvedIfx rIfx;
6799   symbol *lbl, *lbl_done;
6800
6801   unsigned long lit = 0L;
6802   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6803
6804   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6805   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6806   if(result)
6807     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6808   resolveIfx(&rIfx,ifx);
6809   lbl =  newiTempLabel(NULL);
6810   lbl_done =  newiTempLabel(NULL);
6811
6812
6813   /* if the left side is a literal or 
6814      if the right is in a pointer register and left 
6815      is not */
6816   if ((AOP_TYPE(left) == AOP_LIT) || 
6817       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6818     operand *t = right;
6819     right = left;
6820     left = t;
6821   }
6822   if(AOP_TYPE(right) == AOP_LIT)
6823     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6824
6825   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6826     preserve_result = 1;
6827
6828   if(result && !preserve_result)
6829     {
6830       int i;
6831       for(i = 0; i < AOP_SIZE(result); i++)
6832         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6833     }
6834
6835
6836   /* if the right side is a literal then anything goes */
6837   if (AOP_TYPE(right) == AOP_LIT &&
6838       AOP_TYPE(left) != AOP_DIR ) {
6839     switch(size) {
6840     case 2:
6841       genc16bit2lit(left, lit, 0);
6842       emitSKPZ;
6843       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6844       break;
6845     default:
6846       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6847       while (size--) {
6848         if(lit & 0xff) {
6849           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6850           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6851         } else {
6852           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6853         }
6854
6855         emitSKPZ;
6856         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6857         offset++;
6858         if(res_offset < res_size-1)
6859           res_offset++;
6860         lit >>= 8;
6861       }
6862       break;
6863     }
6864   }
6865
6866   /* if the right side is in a register or in direct space or
6867      if the left is a pointer register & right is not */    
6868   else if (AOP_TYPE(right) == AOP_REG ||
6869            AOP_TYPE(right) == AOP_DIR || 
6870            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6871            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6872     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6873     int lbl_key = lbl->key;
6874
6875     if(result) {
6876       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6877       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6878     }else {
6879       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6880       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6881               __FUNCTION__,__LINE__);
6882       return;
6883     }
6884    
6885 /*     switch(size) { */
6886 /*     case 2: */
6887 /*       genc16bit2lit(left, lit, 0); */
6888 /*       emitSKPNZ; */
6889 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6890 /*       break; */
6891 /*     default: */
6892     while (size--) {
6893       int emit_skip=1;
6894       if((AOP_TYPE(left) == AOP_DIR) && 
6895          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6896
6897         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6898         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6899
6900       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6901             
6902         switch (lit & 0xff) {
6903         case 0:
6904           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6905           break;
6906         case 1:
6907           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6908           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6909           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6910           emit_skip=0;
6911           break;
6912         case 0xff:
6913           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6914           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6915           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6916           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6917           emit_skip=0;
6918           break;
6919         default:
6920           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6921           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6922         }
6923         lit >>= 8;
6924
6925       } else {
6926         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6927       }
6928       if(emit_skip) {
6929         if(AOP_TYPE(result) == AOP_CRY) {
6930           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6931           if(rIfx.condition)
6932             emitSKPNZ;
6933           else
6934             emitSKPZ;
6935           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6936         } else {
6937           /* fix me. probably need to check result size too */
6938           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6939           if(rIfx.condition)
6940             emitSKPZ;
6941           else
6942             emitSKPNZ;
6943           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6944           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6945         }
6946         if(ifx)
6947           ifx->generated=1;
6948       }
6949       emit_skip++;
6950       offset++;
6951       if(res_offset < res_size-1)
6952         res_offset++;
6953     }
6954 /*       break; */
6955 /*     } */
6956   } else if(AOP_TYPE(right) == AOP_REG &&
6957             AOP_TYPE(left) != AOP_DIR){
6958
6959     while(size--) {
6960       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6961       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6962       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6963       if(rIfx.condition)
6964         emitSKPNZ;
6965       else
6966         emitSKPZ;
6967       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6968       offset++;
6969       if(res_offset < res_size-1)
6970         res_offset++;
6971     }
6972       
6973   }else{
6974     /* right is a pointer reg need both a & b */
6975     while(size--) {
6976       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6977       if(strcmp(l,"b"))
6978         pic16_emitcode("mov","b,%s",l);
6979       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6980       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6981       offset++;
6982     }
6983   }
6984
6985   if(result && preserve_result)
6986     {
6987       int i;
6988       for(i = 0; i < AOP_SIZE(result); i++)
6989         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6990     }
6991
6992   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6993
6994   if(result && preserve_result)
6995     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6996
6997   if(!rIfx.condition)
6998     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6999
7000   pic16_emitpLabel(lbl->key);
7001
7002   if(result && preserve_result)
7003     {
7004       int i;
7005       for(i = 0; i < AOP_SIZE(result); i++)
7006         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7007
7008       pic16_emitpLabel(lbl_done->key);
7009    }
7010
7011   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7012
7013   if(ifx)
7014     ifx->generated = 1;
7015 }
7016 #endif
7017
7018 #if 0
7019 /*-----------------------------------------------------------------*/
7020 /* gencjne - compare and jump if not equal                         */
7021 /*-----------------------------------------------------------------*/
7022 static void gencjne(operand *left, operand *right, iCode *ifx)
7023 {
7024     symbol *tlbl  = newiTempLabel(NULL);
7025
7026     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7027     gencjneshort(left, right, lbl);
7028
7029     pic16_emitcode("mov","a,%s",one);
7030     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7031     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7032     pic16_emitcode("clr","a");
7033     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7034
7035     pic16_emitpLabel(lbl->key);
7036     pic16_emitpLabel(tlbl->key);
7037
7038 }
7039 #endif
7040
7041
7042 /*-----------------------------------------------------------------*/
7043 /* is_LitOp - check if operand has to be treated as literal        */
7044 /*-----------------------------------------------------------------*/
7045 static bool is_LitOp(operand *op)
7046 {
7047   return ((AOP_TYPE(op) == AOP_LIT)
7048       || ( (AOP_TYPE(op) == AOP_PCODE)
7049           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7050               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7051 }
7052
7053 /*-----------------------------------------------------------------*/
7054 /* is_LitAOp - check if operand has to be treated as literal        */
7055 /*-----------------------------------------------------------------*/
7056 static bool is_LitAOp(asmop *aop)
7057 {
7058   return ((aop->type == AOP_LIT)
7059       || ( (aop->type == AOP_PCODE)
7060           && ( (aop->aopu.pcop->type == PO_LITERAL)
7061               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7062 }
7063
7064
7065
7066 /*-----------------------------------------------------------------*/
7067 /* genCmpEq - generates code for equal to                          */
7068 /*-----------------------------------------------------------------*/
7069 static void genCmpEq (iCode *ic, iCode *ifx)
7070 {
7071   operand *left, *right, *result;
7072   symbol *falselbl = newiTempLabel(NULL);
7073   symbol *donelbl = newiTempLabel(NULL);
7074
7075   int preserve_result = 0;
7076   int generate_result = 0;
7077   int i=0;
7078   unsigned long lit = -1;
7079
7080   FENTRY;
7081   
7082   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7083   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7084   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7085  
7086   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7087
7088   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7089     {
7090       werror(W_POSSBUG2, __FILE__, __LINE__);
7091       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7092       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7093       goto release;
7094     }
7095
7096   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7097     {
7098       operand *tmp = right ;
7099       right = left;
7100       left = tmp;
7101     }
7102
7103   if (AOP_TYPE(right) == AOP_LIT) {
7104     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7105   }
7106
7107   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7108     preserve_result = 1;
7109
7110   if(result && AOP_SIZE(result))
7111     generate_result = 1;
7112
7113   if(generate_result && !preserve_result)
7114     {
7115       for(i = 0; i < AOP_SIZE(result); i++)
7116         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7117     }
7118
7119   for(i=0; i < AOP_SIZE(left); i++)
7120     {
7121       if(AOP_TYPE(left) != AOP_ACC)
7122         {
7123           if(is_LitOp(left))
7124             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7125           else
7126             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7127         }
7128       if(is_LitOp(right)) {
7129         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7130           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7131         }
7132       } else
7133         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7134
7135       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7136     }
7137
7138   // result == true
7139
7140   if(generate_result && preserve_result)
7141     {
7142       for(i = 0; i < AOP_SIZE(result); i++)
7143         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7144     }
7145
7146   if(generate_result)
7147     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7148
7149   if(generate_result && preserve_result)
7150     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7151
7152   if(ifx && IC_TRUE(ifx))
7153     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7154
7155   if(ifx && IC_FALSE(ifx))
7156     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7157
7158   pic16_emitpLabel(falselbl->key);
7159
7160   // result == false
7161
7162   if(ifx && IC_FALSE(ifx))
7163     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7164
7165   if(generate_result && preserve_result)
7166     {
7167       for(i = 0; i < AOP_SIZE(result); i++)
7168         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7169     }
7170
7171   pic16_emitpLabel(donelbl->key);
7172
7173   if(ifx)
7174     ifx->generated = 1;
7175
7176 release:
7177   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7178   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7179   pic16_freeAsmop(result,NULL,ic,TRUE);
7180
7181 }
7182
7183
7184 #if 0
7185 // old version kept for reference
7186
7187 /*-----------------------------------------------------------------*/
7188 /* genCmpEq - generates code for equal to                          */
7189 /*-----------------------------------------------------------------*/
7190 static void genCmpEq (iCode *ic, iCode *ifx)
7191 {
7192     operand *left, *right, *result;
7193     unsigned long lit = 0L;
7194     int size,offset=0;
7195     symbol *falselbl  = newiTempLabel(NULL);
7196
7197
7198     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7199
7200     if(ifx)
7201       DEBUGpic16_emitcode ("; ifx is non-null","");
7202     else
7203       DEBUGpic16_emitcode ("; ifx is null","");
7204
7205     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7206     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7207     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7208
7209     size = max(AOP_SIZE(left),AOP_SIZE(right));
7210
7211     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7212
7213     /* if literal, literal on the right or 
7214     if the right is in a pointer register and left 
7215     is not */
7216     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7217         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7218       operand *tmp = right ;
7219       right = left;
7220       left = tmp;
7221     }
7222
7223
7224     if(ifx && !AOP_SIZE(result)){
7225         symbol *tlbl;
7226         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7227         /* if they are both bit variables */
7228         if (AOP_TYPE(left) == AOP_CRY &&
7229             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7230                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7231             if(AOP_TYPE(right) == AOP_LIT){
7232                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7233                 if(lit == 0L){
7234                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7235                     pic16_emitcode("cpl","c");
7236                 } else if(lit == 1L) {
7237                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7238                 } else {
7239                     pic16_emitcode("clr","c");
7240                 }
7241                 /* AOP_TYPE(right) == AOP_CRY */
7242             } else {
7243                 symbol *lbl = newiTempLabel(NULL);
7244                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7245                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7246                 pic16_emitcode("cpl","c");
7247                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7248             }
7249             /* if true label then we jump if condition
7250             supplied is true */
7251             tlbl = newiTempLabel(NULL);
7252             if ( IC_TRUE(ifx) ) {
7253                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7254                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7255             } else {
7256                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7257                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7258             }
7259             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7260
7261                 {
7262                 /* left and right are both bit variables, result is carry */
7263                         resolvedIfx rIfx;
7264               
7265                         resolveIfx(&rIfx,ifx);
7266
7267                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7268                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7269                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7270                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7271                         genSkipz2(&rIfx,0);
7272                 }
7273         } else {
7274
7275                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7276
7277                         /* They're not both bit variables. Is the right a literal? */
7278                         if(AOP_TYPE(right) == AOP_LIT) {
7279                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7280             
7281                         switch(size) {
7282
7283                                 case 1:
7284                                         switch(lit & 0xff) {
7285                                                 case 1:
7286                                                                 if ( IC_TRUE(ifx) ) {
7287                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7288                                                                         emitSKPNZ;
7289                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7290                                                                 } else {
7291                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7292                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7293                                                                 }
7294                                                                 break;
7295                                                 case 0xff:
7296                                                                 if ( IC_TRUE(ifx) ) {
7297                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7298                                                                         emitSKPNZ;
7299                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7300                                                                 } else {
7301                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7302                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7303                                                                 }
7304                                                                 break;
7305                                                 default:
7306                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7307                                                                 if(lit)
7308                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7309                                                                 genSkip(ifx,'z');
7310                                         } // switch lit
7311
7312
7313                                         /* end of size == 1 */
7314                                         break;
7315               
7316                                 case 2:
7317                                         genc16bit2lit(left,lit,offset);
7318                                         genSkip(ifx,'z');
7319                                         break;
7320                                         /* end of size == 2 */
7321
7322                                 default:
7323                                         /* size is 4 */
7324                                         if(lit==0) {
7325                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7326                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7327                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7328                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7329                                                 genSkip(ifx,'z');
7330                                         } else {
7331                                                 /* search for patterns that can be optimized */
7332
7333                                                 genc16bit2lit(left,lit,0);
7334                                                 lit >>= 16;
7335                                                 if(lit) {
7336                                                                 if(IC_TRUE(ifx))
7337                                                                 emitSKPZ; // if hi word unequal
7338                                                                 else
7339                                                                 emitSKPNZ; // if hi word equal
7340                                                                 // fail early
7341                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7342                                                         genc16bit2lit(left,lit,2);
7343                                                         genSkip(ifx,'z');
7344                                                 } else {
7345                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7346                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7347                                                         genSkip(ifx,'z');
7348                                                 }
7349                                         }
7350                                                 pic16_emitpLabel(falselbl->key);
7351                                                 break;
7352
7353                         } // switch size
7354           
7355                         ifx->generated = 1;
7356                         goto release ;
7357             
7358
7359           } else if(AOP_TYPE(right) == AOP_CRY ) {
7360             /* we know the left is not a bit, but that the right is */
7361             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7362             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7363                       pic16_popGet(AOP(right),offset));
7364             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7365
7366             /* if the two are equal, then W will be 0 and the Z bit is set
7367              * we could test Z now, or go ahead and check the high order bytes if
7368              * the variable we're comparing is larger than a byte. */
7369
7370             while(--size)
7371               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7372
7373             if ( IC_TRUE(ifx) ) {
7374               emitSKPNZ;
7375               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7376               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7377             } else {
7378               emitSKPZ;
7379               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7380               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7381             }
7382
7383           } else {
7384             /* They're both variables that are larger than bits */
7385             int s = size;
7386
7387             tlbl = newiTempLabel(NULL);
7388
7389             while(size--) {
7390               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7391               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7392
7393               if ( IC_TRUE(ifx) ) {
7394                 if(size) {
7395                   emitSKPZ;
7396                 
7397                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7398
7399                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7400                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7401                 } else {
7402                   emitSKPNZ;
7403
7404                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7405
7406
7407                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7408                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7409                 }
7410               } else {
7411                 emitSKPZ;
7412
7413                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7414
7415                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7416                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7417               }
7418               offset++;
7419             }
7420             if(s>1 && IC_TRUE(ifx)) {
7421               pic16_emitpLabel(tlbl->key);
7422               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7423             }
7424           }
7425         }
7426         /* mark the icode as generated */
7427         ifx->generated = 1;
7428         goto release ;
7429     }
7430
7431     /* if they are both bit variables */
7432     if (AOP_TYPE(left) == AOP_CRY &&
7433         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7434         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7435         if(AOP_TYPE(right) == AOP_LIT){
7436             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7437             if(lit == 0L){
7438                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7439                 pic16_emitcode("cpl","c");
7440             } else if(lit == 1L) {
7441                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7442             } else {
7443                 pic16_emitcode("clr","c");
7444             }
7445             /* AOP_TYPE(right) == AOP_CRY */
7446         } else {
7447             symbol *lbl = newiTempLabel(NULL);
7448             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7449             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7450             pic16_emitcode("cpl","c");
7451             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7452         }
7453         /* c = 1 if egal */
7454         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7455             pic16_outBitC(result);
7456             goto release ;
7457         }
7458         if (ifx) {
7459             genIfxJump (ifx,"c");
7460             goto release ;
7461         }
7462         /* if the result is used in an arithmetic operation
7463         then put the result in place */
7464         pic16_outBitC(result);
7465     } else {
7466       
7467       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7468       gencjne(left,right,result,ifx);
7469 /*
7470       if(ifx) 
7471         gencjne(left,right,newiTempLabel(NULL));
7472       else {
7473         if(IC_TRUE(ifx)->key)
7474           gencjne(left,right,IC_TRUE(ifx)->key);
7475         else
7476           gencjne(left,right,IC_FALSE(ifx)->key);
7477         ifx->generated = 1;
7478         goto release ;
7479       }
7480       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7481         pic16_aopPut(AOP(result),"a",0);
7482         goto release ;
7483       }
7484
7485       if (ifx) {
7486         genIfxJump (ifx,"a");
7487         goto release ;
7488       }
7489 */
7490       /* if the result is used in an arithmetic operation
7491          then put the result in place */
7492 /*
7493       if (AOP_TYPE(result) != AOP_CRY) 
7494         pic16_outAcc(result);
7495 */
7496       /* leave the result in acc */
7497     }
7498
7499 release:
7500     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7501     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7502     pic16_freeAsmop(result,NULL,ic,TRUE);
7503 }
7504 #endif
7505
7506 /*-----------------------------------------------------------------*/
7507 /* ifxForOp - returns the icode containing the ifx for operand     */
7508 /*-----------------------------------------------------------------*/
7509 static iCode *ifxForOp ( operand *op, iCode *ic )
7510 {
7511   FENTRY2;
7512
7513     /* if true symbol then needs to be assigned */
7514     if (IS_TRUE_SYMOP(op))
7515         return NULL ;
7516
7517     /* if this has register type condition and
7518     the next instruction is ifx with the same operand
7519     and live to of the operand is upto the ifx only then */
7520     if (ic->next
7521         && ic->next->op == IFX
7522         && IC_COND(ic->next)->key == op->key
7523         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7524         ) {
7525                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7526           return ic->next;
7527     }
7528
7529     /*
7530     if (ic->next &&
7531         ic->next->op == IFX &&
7532         IC_COND(ic->next)->key == op->key) {
7533       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7534       return ic->next;
7535     }
7536     */
7537
7538     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7539     if (ic->next &&
7540         ic->next->op == IFX)
7541       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7542
7543     if (ic->next &&
7544         ic->next->op == IFX &&
7545         IC_COND(ic->next)->key == op->key) {
7546       DEBUGpic16_emitcode ("; "," key is okay");
7547       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7548                            OP_SYMBOL(op)->liveTo,
7549                            ic->next->seq);
7550     }
7551
7552 #if 0
7553     /* the code below is completely untested
7554      * it just allows ulong2fs.c compile -- VR */
7555          
7556     ic = ic->next;
7557     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7558                                         __FILE__, __FUNCTION__, __LINE__);
7559         
7560     /* if this has register type condition and
7561     the next instruction is ifx with the same operand
7562     and live to of the operand is upto the ifx only then */
7563     if (ic->next &&
7564         ic->next->op == IFX &&
7565         IC_COND(ic->next)->key == op->key &&
7566         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7567         return ic->next;
7568
7569     if (ic->next &&
7570         ic->next->op == IFX &&
7571         IC_COND(ic->next)->key == op->key) {
7572       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7573       return ic->next;
7574     }
7575
7576     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7577                                         __FILE__, __FUNCTION__, __LINE__);
7578
7579 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7580 #endif
7581
7582     return NULL;
7583 }
7584 /*-----------------------------------------------------------------*/
7585 /* genAndOp - for && operation                                     */
7586 /*-----------------------------------------------------------------*/
7587 static void genAndOp (iCode *ic)
7588 {
7589   operand *left,*right, *result;
7590 /*     symbol *tlbl; */
7591
7592     FENTRY;
7593
7594     /* note here that && operations that are in an
7595     if statement are taken away by backPatchLabels
7596     only those used in arthmetic operations remain */
7597     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7598     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7599     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7600
7601     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7602
7603     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7604     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7605     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7606
7607     /* if both are bit variables */
7608 /*     if (AOP_TYPE(left) == AOP_CRY && */
7609 /*         AOP_TYPE(right) == AOP_CRY ) { */
7610 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7611 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7612 /*         pic16_outBitC(result); */
7613 /*     } else { */
7614 /*         tlbl = newiTempLabel(NULL); */
7615 /*         pic16_toBoolean(left);     */
7616 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7617 /*         pic16_toBoolean(right); */
7618 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7619 /*         pic16_outBitAcc(result); */
7620 /*     } */
7621
7622     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7623     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7624     pic16_freeAsmop(result,NULL,ic,TRUE);
7625 }
7626
7627
7628 /*-----------------------------------------------------------------*/
7629 /* genOrOp - for || operation                                      */
7630 /*-----------------------------------------------------------------*/
7631 /*
7632   tsd pic port -
7633   modified this code, but it doesn't appear to ever get called
7634 */
7635
7636 static void genOrOp (iCode *ic)
7637 {
7638   operand *left,*right, *result;
7639   symbol *tlbl;
7640
7641     FENTRY;  
7642
7643   /* note here that || operations that are in an
7644     if statement are taken away by backPatchLabels
7645     only those used in arthmetic operations remain */
7646     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7647     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7648     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7649
7650     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7651
7652     /* if both are bit variables */
7653     if (AOP_TYPE(left) == AOP_CRY &&
7654         AOP_TYPE(right) == AOP_CRY ) {
7655       pic16_emitcode("clrc","");
7656       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7657                AOP(left)->aopu.aop_dir,
7658                AOP(left)->aopu.aop_dir);
7659       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7660                AOP(right)->aopu.aop_dir,
7661                AOP(right)->aopu.aop_dir);
7662       pic16_emitcode("setc","");
7663
7664     } else {
7665         tlbl = newiTempLabel(NULL);
7666         pic16_toBoolean(left);
7667         emitSKPZ;
7668         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7669         pic16_toBoolean(right);
7670         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7671
7672         pic16_outBitAcc(result);
7673     }
7674
7675     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7677     pic16_freeAsmop(result,NULL,ic,TRUE);            
7678 }
7679
7680 /*-----------------------------------------------------------------*/
7681 /* isLiteralBit - test if lit == 2^n                               */
7682 /*-----------------------------------------------------------------*/
7683 static int isLiteralBit(unsigned long lit)
7684 {
7685     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7686     0x100L,0x200L,0x400L,0x800L,
7687     0x1000L,0x2000L,0x4000L,0x8000L,
7688     0x10000L,0x20000L,0x40000L,0x80000L,
7689     0x100000L,0x200000L,0x400000L,0x800000L,
7690     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7691     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7692     int idx;
7693     
7694     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7695     for(idx = 0; idx < 32; idx++)
7696         if(lit == pw[idx])
7697             return idx+1;
7698     return 0;
7699 }
7700
7701 /*-----------------------------------------------------------------*/
7702 /* continueIfTrue -                                                */
7703 /*-----------------------------------------------------------------*/
7704 static void continueIfTrue (iCode *ic)
7705 {
7706   FENTRY;
7707   if(IC_TRUE(ic))
7708     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7709   ic->generated = 1;
7710 }
7711
7712 /*-----------------------------------------------------------------*/
7713 /* jmpIfTrue -                                                     */
7714 /*-----------------------------------------------------------------*/
7715 static void jumpIfTrue (iCode *ic)
7716 {
7717   FENTRY;
7718   if(!IC_TRUE(ic))
7719     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7720   ic->generated = 1;
7721 }
7722
7723 /*-----------------------------------------------------------------*/
7724 /* jmpTrueOrFalse -                                                */
7725 /*-----------------------------------------------------------------*/
7726 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7727 {
7728   // ugly but optimized by peephole
7729   FENTRY;
7730   if(IC_TRUE(ic)){
7731     symbol *nlbl = newiTempLabel(NULL);
7732       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7733       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7734       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7735       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7736   } else {
7737     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7738     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7739   }
7740   ic->generated = 1;
7741 }
7742
7743 /*-----------------------------------------------------------------*/
7744 /* genAnd  - code for and                                          */
7745 /*-----------------------------------------------------------------*/
7746 static void genAnd (iCode *ic, iCode *ifx)
7747 {
7748   operand *left, *right, *result;
7749   int size, offset=0;  
7750   unsigned long lit = 0L;
7751   int bytelit = 0;
7752   resolvedIfx rIfx;
7753
7754     FENTRY;
7755     
7756   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7757   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7758   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7759
7760   resolveIfx(&rIfx,ifx);
7761
7762   /* if left is a literal & right is not then exchange them */
7763   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7764       AOP_NEEDSACC(left)) {
7765     operand *tmp = right ;
7766     right = left;
7767     left = tmp;
7768   }
7769
7770   /* if result = right then exchange them */
7771   if(pic16_sameRegs(AOP(result),AOP(right))){
7772     operand *tmp = right ;
7773     right = left;
7774     left = tmp;
7775   }
7776
7777   /* if right is bit then exchange them */
7778   if (AOP_TYPE(right) == AOP_CRY &&
7779       AOP_TYPE(left) != AOP_CRY){
7780     operand *tmp = right ;
7781     right = left;
7782     left = tmp;
7783   }
7784   if(AOP_TYPE(right) == AOP_LIT)
7785     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7786
7787   size = AOP_SIZE(result);
7788
7789   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7790
7791   // if(bit & yy)
7792   // result = bit & yy;
7793   if (AOP_TYPE(left) == AOP_CRY){
7794     // c = bit & literal;
7795     if(AOP_TYPE(right) == AOP_LIT){
7796       if(lit & 1) {
7797         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7798           // no change
7799           goto release;
7800         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7801       } else {
7802         // bit(result) = 0;
7803         if(size && (AOP_TYPE(result) == AOP_CRY)){
7804           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7805           goto release;
7806         }
7807         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7808           jumpIfTrue(ifx);
7809           goto release;
7810         }
7811         pic16_emitcode("clr","c");
7812       }
7813     } else {
7814       if (AOP_TYPE(right) == AOP_CRY){
7815         // c = bit & bit;
7816         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7817         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7818       } else {
7819         // c = bit & val;
7820         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7821         // c = lsb
7822         pic16_emitcode("rrc","a");
7823         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7824       }
7825     }
7826     // bit = c
7827     // val = c
7828     if(size)
7829       pic16_outBitC(result);
7830     // if(bit & ...)
7831     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7832       genIfxJump(ifx, "c");           
7833     goto release ;
7834   }
7835
7836   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7837   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7838   if((AOP_TYPE(right) == AOP_LIT) &&
7839      (AOP_TYPE(result) == AOP_CRY) &&
7840      (AOP_TYPE(left) != AOP_CRY)){
7841     int posbit = isLiteralBit(lit);
7842     /* left &  2^n */
7843     if(posbit){
7844       posbit--;
7845       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7846       // bit = left & 2^n
7847       if(size)
7848         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7849       // if(left &  2^n)
7850       else{
7851         if(ifx){
7852 /*
7853           if(IC_TRUE(ifx)) {
7854             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7855             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7856           } else {
7857             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7858             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7859           }
7860 */
7861         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7862         size = AOP_SIZE(left);
7863
7864         {
7865           int bp = posbit, ofs=0;
7866           
7867             while(bp > 7) {
7868               bp -= 8;
7869               ofs++;
7870             }
7871         
7872           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7873                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7874
7875         }
7876 /*
7877           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7878                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7879 */
7880           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7881           
7882           ifx->generated = 1;
7883         }
7884         goto release;
7885       }
7886     } else {
7887       symbol *tlbl = newiTempLabel(NULL);
7888       int sizel = AOP_SIZE(left);
7889
7890       if(size)
7891         emitSETC;
7892
7893       while(sizel--) {
7894         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7895
7896           /* patch provided by Aaron Colwell */
7897           if((posbit = isLiteralBit(bytelit)) != 0) {
7898               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7899                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7900                                                 (posbit-1),0, PO_GPR_REGISTER));
7901
7902               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7903 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7904           } else {
7905               if (bytelit == 0xff) {
7906                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7907                    * a peephole could optimize it out -- VR */
7908                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7909               } else {
7910                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7911                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7912               }
7913
7914               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7915                             pic16_popGetLabel(tlbl->key));
7916           }
7917         
7918 #if 0
7919           /* old code, left here for reference -- VR 09/2004 */
7920           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921           // byte ==  2^n ?
7922           if((posbit = isLiteralBit(bytelit)) != 0)
7923             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7924           else{
7925             if(bytelit != 0x0FFL)
7926               pic16_emitcode("anl","a,%s",
7927                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7928             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7929           }
7930 #endif
7931         }
7932         offset++;
7933       }
7934       // bit = left & literal
7935       if(size) {
7936         emitCLRC;
7937         pic16_emitpLabel(tlbl->key);
7938       }
7939       // if(left & literal)
7940       else {
7941         if(ifx) {
7942           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7943           ifx->generated = 1;
7944         }
7945         pic16_emitpLabel(tlbl->key);
7946         goto release;
7947       }
7948     }
7949
7950     pic16_outBitC(result);
7951     goto release ;
7952   }
7953
7954   /* if left is same as result */
7955   if(pic16_sameRegs(AOP(result),AOP(left))){
7956     int know_W = -1;
7957     for(;size--; offset++,lit>>=8) {
7958       if(AOP_TYPE(right) == AOP_LIT){
7959         switch(lit & 0xff) {
7960         case 0x00:
7961           /*  and'ing with 0 has clears the result */
7962 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7963           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7964           break;
7965         case 0xff:
7966           /* and'ing with 0xff is a nop when the result and left are the same */
7967           break;
7968
7969         default:
7970           {
7971             int p = pic16_my_powof2( (~lit) & 0xff );
7972             if(p>=0) {
7973               /* only one bit is set in the literal, so use a bcf instruction */
7974 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7975               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7976
7977             } else {
7978               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7979               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7980               if(know_W != (lit&0xff))
7981                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7982               know_W = lit &0xff;
7983               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7984             }
7985           }    
7986         }
7987       } else {
7988         if (AOP_TYPE(left) == AOP_ACC) {
7989           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7990         } else {                    
7991           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7992           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7993
7994         }
7995       }
7996     }
7997
7998   } else {
7999     // left & result in different registers
8000     if(AOP_TYPE(result) == AOP_CRY){
8001       // result = bit
8002       // if(size), result in bit
8003       // if(!size && ifx), conditional oper: if(left & right)
8004       symbol *tlbl = newiTempLabel(NULL);
8005       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8006       if(size)
8007         pic16_emitcode("setb","c");
8008       while(sizer--){
8009         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8010         pic16_emitcode("anl","a,%s",
8011                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8012         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8013         offset++;
8014       }
8015       if(size){
8016         CLRC;
8017         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8018         pic16_outBitC(result);
8019       } else if(ifx)
8020         jmpTrueOrFalse(ifx, tlbl);
8021     } else {
8022       for(;(size--);offset++) {
8023         // normal case
8024         // result = left & right
8025         if(AOP_TYPE(right) == AOP_LIT){
8026           int t = (lit >> (offset*8)) & 0x0FFL;
8027           switch(t) { 
8028           case 0x00:
8029             pic16_emitcode("clrf","%s",
8030                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8031             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8032             break;
8033           case 0xff:
8034             pic16_emitcode("movf","%s,w",
8035                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8036             pic16_emitcode("movwf","%s",
8037                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8038             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8039             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8040             break;
8041           default:
8042             pic16_emitcode("movlw","0x%x",t);
8043             pic16_emitcode("andwf","%s,w",
8044                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8045             pic16_emitcode("movwf","%s",
8046                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8047               
8048             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8049             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8050             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8051           }
8052           continue;
8053         }
8054
8055         if (AOP_TYPE(left) == AOP_ACC) {
8056           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8057           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8058         } else {
8059           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8060           pic16_emitcode("andwf","%s,w",
8061                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8062           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8063           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8064         }
8065         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8066         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8067       }
8068     }
8069   }
8070
8071   release :
8072     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8073   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8074   pic16_freeAsmop(result,NULL,ic,TRUE);     
8075 }
8076
8077 /*-----------------------------------------------------------------*/
8078 /* genOr  - code for or                                            */
8079 /*-----------------------------------------------------------------*/
8080 static void genOr (iCode *ic, iCode *ifx)
8081 {
8082     operand *left, *right, *result;
8083     int size, offset=0;
8084     unsigned long lit = 0L;
8085
8086     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8087
8088     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8089     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8090     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8091
8092     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8093
8094     /* if left is a literal & right is not then exchange them */
8095     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8096         AOP_NEEDSACC(left)) {
8097         operand *tmp = right ;
8098         right = left;
8099         left = tmp;
8100     }
8101
8102     /* if result = right then exchange them */
8103     if(pic16_sameRegs(AOP(result),AOP(right))){
8104         operand *tmp = right ;
8105         right = left;
8106         left = tmp;
8107     }
8108
8109     /* if right is bit then exchange them */
8110     if (AOP_TYPE(right) == AOP_CRY &&
8111         AOP_TYPE(left) != AOP_CRY){
8112         operand *tmp = right ;
8113         right = left;
8114         left = tmp;
8115     }
8116
8117     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8118
8119     if(AOP_TYPE(right) == AOP_LIT)
8120         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8121
8122     size = AOP_SIZE(result);
8123
8124     // if(bit | yy)
8125     // xx = bit | yy;
8126     if (AOP_TYPE(left) == AOP_CRY){
8127         if(AOP_TYPE(right) == AOP_LIT){
8128             // c = bit & literal;
8129             if(lit){
8130                 // lit != 0 => result = 1
8131                 if(AOP_TYPE(result) == AOP_CRY){
8132                   if(size)
8133                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8134                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8135                   //     AOP(result)->aopu.aop_dir,
8136                   //     AOP(result)->aopu.aop_dir);
8137                     else if(ifx)
8138                         continueIfTrue(ifx);
8139                     goto release;
8140                 }
8141             } else {
8142                 // lit == 0 => result = left
8143                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8144                     goto release;
8145                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8146             }
8147         } else {
8148             if (AOP_TYPE(right) == AOP_CRY){
8149               if(pic16_sameRegs(AOP(result),AOP(left))){
8150                 // c = bit | bit;
8151                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8152                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8153                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8154
8155                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8156                          AOP(result)->aopu.aop_dir,
8157                          AOP(result)->aopu.aop_dir);
8158                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8159                          AOP(right)->aopu.aop_dir,
8160                          AOP(right)->aopu.aop_dir);
8161                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8162                          AOP(result)->aopu.aop_dir,
8163                          AOP(result)->aopu.aop_dir);
8164               } else {
8165                 if( AOP_TYPE(result) == AOP_ACC) {
8166                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8167                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8168                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8169                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8170
8171                 } else {
8172
8173                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8174                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8175                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8176                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8177
8178                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8179                                  AOP(result)->aopu.aop_dir,
8180                                  AOP(result)->aopu.aop_dir);
8181                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8182                                  AOP(right)->aopu.aop_dir,
8183                                  AOP(right)->aopu.aop_dir);
8184                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8185                                  AOP(left)->aopu.aop_dir,
8186                                  AOP(left)->aopu.aop_dir);
8187                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8188                                  AOP(result)->aopu.aop_dir,
8189                                  AOP(result)->aopu.aop_dir);
8190                 }
8191               }
8192             } else {
8193                 // c = bit | val;
8194                 symbol *tlbl = newiTempLabel(NULL);
8195                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8196
8197
8198                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8199                 if( AOP_TYPE(right) == AOP_ACC) {
8200                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8201                   emitSKPNZ;
8202                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8203                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8204                 }
8205
8206
8207
8208                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8209                     pic16_emitcode(";XXX setb","c");
8210                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8211                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8212                 pic16_toBoolean(right);
8213                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8214                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8215                     jmpTrueOrFalse(ifx, tlbl);
8216                     goto release;
8217                 } else {
8218                     CLRC;
8219                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8220                 }
8221             }
8222         }
8223         // bit = c
8224         // val = c
8225         if(size)
8226             pic16_outBitC(result);
8227         // if(bit | ...)
8228         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8229             genIfxJump(ifx, "c");           
8230         goto release ;
8231     }
8232
8233     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8234     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8235     if((AOP_TYPE(right) == AOP_LIT) &&
8236        (AOP_TYPE(result) == AOP_CRY) &&
8237        (AOP_TYPE(left) != AOP_CRY)){
8238         if(lit){
8239           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8240             // result = 1
8241             if(size)
8242                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8243             else 
8244                 continueIfTrue(ifx);
8245             goto release;
8246         } else {
8247           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8248             // lit = 0, result = boolean(left)
8249             if(size)
8250                 pic16_emitcode(";XXX setb","c");
8251             pic16_toBoolean(right);
8252             if(size){
8253                 symbol *tlbl = newiTempLabel(NULL);
8254                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8255                 CLRC;
8256                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8257             } else {
8258                 genIfxJump (ifx,"a");
8259                 goto release;
8260             }
8261         }
8262         pic16_outBitC(result);
8263         goto release ;
8264     }
8265
8266     /* if left is same as result */
8267     if(pic16_sameRegs(AOP(result),AOP(left))){
8268       int know_W = -1;
8269       for(;size--; offset++,lit>>=8) {
8270         if(AOP_TYPE(right) == AOP_LIT){
8271           if((lit & 0xff) == 0)
8272             /*  or'ing with 0 has no effect */
8273             continue;
8274           else {
8275             int p = pic16_my_powof2(lit & 0xff);
8276             if(p>=0) {
8277               /* only one bit is set in the literal, so use a bsf instruction */
8278               pic16_emitpcode(POC_BSF,
8279                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8280             } else {
8281               if(know_W != (lit & 0xff))
8282                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8283               know_W = lit & 0xff;
8284               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8285             }
8286                     
8287           }
8288         } else {
8289           if (AOP_TYPE(left) == AOP_ACC) {
8290             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8291             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8292           } else {                  
8293             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8294             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8295
8296             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8297             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8298
8299           }
8300         }
8301       }
8302     } else {
8303         // left & result in different registers
8304         if(AOP_TYPE(result) == AOP_CRY){
8305             // result = bit
8306             // if(size), result in bit
8307             // if(!size && ifx), conditional oper: if(left | right)
8308             symbol *tlbl = newiTempLabel(NULL);
8309             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8310             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8311
8312
8313             if(size)
8314                 pic16_emitcode(";XXX setb","c");
8315             while(sizer--){
8316                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8317                 pic16_emitcode(";XXX orl","a,%s",
8318                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8319                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8320                 offset++;
8321             }
8322             if(size){
8323                 CLRC;
8324                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8325                 pic16_outBitC(result);
8326             } else if(ifx)
8327                 jmpTrueOrFalse(ifx, tlbl);
8328         } else for(;(size--);offset++){
8329           // normal case
8330           // result = left & right
8331           if(AOP_TYPE(right) == AOP_LIT){
8332             int t = (lit >> (offset*8)) & 0x0FFL;
8333             switch(t) { 
8334             case 0x00:
8335               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8336               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8337
8338               pic16_emitcode("movf","%s,w",
8339                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8340               pic16_emitcode("movwf","%s",
8341                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8342               break;
8343             default:
8344               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8345               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8346               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8347
8348               pic16_emitcode("movlw","0x%x",t);
8349               pic16_emitcode("iorwf","%s,w",
8350                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8351               pic16_emitcode("movwf","%s",
8352                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8353               
8354             }
8355             continue;
8356           }
8357
8358           // faster than result <- left, anl result,right
8359           // and better if result is SFR
8360           if (AOP_TYPE(left) == AOP_ACC) {
8361             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8362             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8363           } else {
8364             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8365             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8366
8367             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8368             pic16_emitcode("iorwf","%s,w",
8369                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8370           }
8371           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8372           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8373         }
8374     }
8375
8376 release :
8377     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8378     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8379     pic16_freeAsmop(result,NULL,ic,TRUE);     
8380 }
8381
8382 /*-----------------------------------------------------------------*/
8383 /* genXor - code for xclusive or                                   */
8384 /*-----------------------------------------------------------------*/
8385 static void genXor (iCode *ic, iCode *ifx)
8386 {
8387   operand *left, *right, *result;
8388   int size, offset=0;
8389   unsigned long lit = 0L;
8390
8391   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8392
8393   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8394   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8395   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8396
8397   /* if left is a literal & right is not ||
8398      if left needs acc & right does not */
8399   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8400       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8401     operand *tmp = right ;
8402     right = left;
8403     left = tmp;
8404   }
8405
8406   /* if result = right then exchange them */
8407   if(pic16_sameRegs(AOP(result),AOP(right))){
8408     operand *tmp = right ;
8409     right = left;
8410     left = tmp;
8411   }
8412
8413   /* if right is bit then exchange them */
8414   if (AOP_TYPE(right) == AOP_CRY &&
8415       AOP_TYPE(left) != AOP_CRY){
8416     operand *tmp = right ;
8417     right = left;
8418     left = tmp;
8419   }
8420   if(AOP_TYPE(right) == AOP_LIT)
8421     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8422
8423   size = AOP_SIZE(result);
8424
8425   // if(bit ^ yy)
8426   // xx = bit ^ yy;
8427   if (AOP_TYPE(left) == AOP_CRY){
8428     if(AOP_TYPE(right) == AOP_LIT){
8429       // c = bit & literal;
8430       if(lit>>1){
8431         // lit>>1  != 0 => result = 1
8432         if(AOP_TYPE(result) == AOP_CRY){
8433           if(size)
8434             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8435             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8436           else if(ifx)
8437             continueIfTrue(ifx);
8438           goto release;
8439         }
8440         pic16_emitcode("setb","c");
8441       } else{
8442         // lit == (0 or 1)
8443         if(lit == 0){
8444           // lit == 0, result = left
8445           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8446             goto release;
8447           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8448         } else{
8449           // lit == 1, result = not(left)
8450           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8451             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8452             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8453             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8454             goto release;
8455           } else {
8456             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8457             pic16_emitcode("cpl","c");
8458           }
8459         }
8460       }
8461
8462     } else {
8463       // right != literal
8464       symbol *tlbl = newiTempLabel(NULL);
8465       if (AOP_TYPE(right) == AOP_CRY){
8466         // c = bit ^ bit;
8467         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8468       }
8469       else{
8470         int sizer = AOP_SIZE(right);
8471         // c = bit ^ val
8472         // if val>>1 != 0, result = 1
8473         pic16_emitcode("setb","c");
8474         while(sizer){
8475           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8476           if(sizer == 1)
8477             // test the msb of the lsb
8478             pic16_emitcode("anl","a,#0xfe");
8479           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8480           sizer--;
8481         }
8482         // val = (0,1)
8483         pic16_emitcode("rrc","a");
8484       }
8485       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8486       pic16_emitcode("cpl","c");
8487       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8488     }
8489     // bit = c
8490     // val = c
8491     if(size)
8492       pic16_outBitC(result);
8493     // if(bit | ...)
8494     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8495       genIfxJump(ifx, "c");           
8496     goto release ;
8497   }
8498
8499   if(pic16_sameRegs(AOP(result),AOP(left))){
8500     /* if left is same as result */
8501     for(;size--; offset++) {
8502       if(AOP_TYPE(right) == AOP_LIT){
8503         int t  = (lit >> (offset*8)) & 0x0FFL;
8504         if(t == 0x00L)
8505           continue;
8506         else
8507           if (IS_AOP_PREG(left)) {
8508             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8509             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8510             pic16_aopPut(AOP(result),"a",offset);
8511           } else {
8512             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8513             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8514             pic16_emitcode("xrl","%s,%s",
8515                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8516                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8517           }
8518       } else {
8519         if (AOP_TYPE(left) == AOP_ACC)
8520           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8521         else {
8522           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8523           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8524 /*
8525           if (IS_AOP_PREG(left)) {
8526             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8527             pic16_aopPut(AOP(result),"a",offset);
8528           } else
8529             pic16_emitcode("xrl","%s,a",
8530                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8531 */
8532         }
8533       }
8534     }
8535   } else {
8536     // left & result in different registers
8537     if(AOP_TYPE(result) == AOP_CRY){
8538       // result = bit
8539       // if(size), result in bit
8540       // if(!size && ifx), conditional oper: if(left ^ right)
8541       symbol *tlbl = newiTempLabel(NULL);
8542       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8543       if(size)
8544         pic16_emitcode("setb","c");
8545       while(sizer--){
8546         if((AOP_TYPE(right) == AOP_LIT) &&
8547            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8548           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8549         } else {
8550           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8551           pic16_emitcode("xrl","a,%s",
8552                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8553         }
8554         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8555         offset++;
8556       }
8557       if(size){
8558         CLRC;
8559         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8560         pic16_outBitC(result);
8561       } else if(ifx)
8562         jmpTrueOrFalse(ifx, tlbl);
8563     } else for(;(size--);offset++){
8564       // normal case
8565       // result = left & right
8566       if(AOP_TYPE(right) == AOP_LIT){
8567         int t = (lit >> (offset*8)) & 0x0FFL;
8568         switch(t) { 
8569         case 0x00:
8570           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8571           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8572           pic16_emitcode("movf","%s,w",
8573                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8574           pic16_emitcode("movwf","%s",
8575                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8576           break;
8577         case 0xff:
8578           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8579           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8580           pic16_emitcode("comf","%s,w",
8581                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8582           pic16_emitcode("movwf","%s",
8583                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8584           break;
8585         default:
8586           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8587           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8588           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8589           pic16_emitcode("movlw","0x%x",t);
8590           pic16_emitcode("xorwf","%s,w",
8591                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8592           pic16_emitcode("movwf","%s",
8593                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8594
8595         }
8596         continue;
8597       }
8598
8599       // faster than result <- left, anl result,right
8600       // and better if result is SFR
8601       if (AOP_TYPE(left) == AOP_ACC) {
8602         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8603         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8604       } else {
8605         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8606         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8607         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8608         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8609       }
8610       if ( AOP_TYPE(result) != AOP_ACC){
8611         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8612         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8613       }
8614     }
8615   }
8616
8617   release :
8618     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8619   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8620   pic16_freeAsmop(result,NULL,ic,TRUE);     
8621 }
8622
8623 /*-----------------------------------------------------------------*/
8624 /* genInline - write the inline code out                           */
8625 /*-----------------------------------------------------------------*/
8626 static void genInline (iCode *ic)
8627 {
8628   char *buffer, *bp, *bp1;
8629     
8630         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8631
8632         _G.inLine += (!options.asmpeep);
8633
8634         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8635         strcpy(buffer,IC_INLINE(ic));
8636
8637         while((bp1=strstr(bp, "\\n"))) {
8638           *bp1++ = '\n';
8639           *bp1++ = ' ';
8640           bp = bp1;
8641         }
8642         bp = bp1 = buffer;
8643         
8644         /* emit each line as a code */
8645         while (*bp) {
8646                 if (*bp == '\n') {
8647                         *bp++ = '\0';
8648
8649                         if(*bp1)
8650                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8651                         bp1 = bp;
8652                 } else {
8653                         if (*bp == ':') {
8654                                 bp++;
8655                                 *bp = '\0';
8656                                 bp++;
8657
8658                                 /* print label, use this special format with NULL directive
8659                                  * to denote that the argument should not be indented with tab */
8660                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8661                                 bp1 = bp;
8662                         } else
8663                                 bp++;
8664                 }
8665         }
8666
8667         if ((bp1 != bp) && *bp1)
8668                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8669
8670
8671     Safe_free(buffer);
8672
8673     _G.inLine -= (!options.asmpeep);
8674 }
8675
8676 /*-----------------------------------------------------------------*/
8677 /* genRRC - rotate right with carry                                */
8678 /*-----------------------------------------------------------------*/
8679 static void genRRC (iCode *ic)
8680 {
8681   operand *left , *result ;
8682   int size, offset = 0, same;
8683
8684   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8685
8686   /* rotate right with carry */
8687   left = IC_LEFT(ic);
8688   result=IC_RESULT(ic);
8689   pic16_aopOp (left,ic,FALSE);
8690   pic16_aopOp (result,ic,FALSE);
8691
8692   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8693
8694   same = pic16_sameRegs(AOP(result),AOP(left));
8695
8696   size = AOP_SIZE(result);    
8697
8698   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8699
8700   /* get the lsb and put it into the carry */
8701   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8702
8703   offset = 0 ;
8704
8705   while(size--) {
8706
8707     if(same) {
8708       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8709     } else {
8710       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8711       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8712     }
8713
8714     offset++;
8715   }
8716
8717   pic16_freeAsmop(left,NULL,ic,TRUE);
8718   pic16_freeAsmop(result,NULL,ic,TRUE);
8719 }
8720
8721 /*-----------------------------------------------------------------*/
8722 /* genRLC - generate code for rotate left with carry               */
8723 /*-----------------------------------------------------------------*/
8724 static void genRLC (iCode *ic)
8725 {    
8726   operand *left , *result ;
8727   int size, offset = 0;
8728   int same;
8729
8730   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8731   /* rotate right with carry */
8732   left = IC_LEFT(ic);
8733   result=IC_RESULT(ic);
8734   pic16_aopOp (left,ic,FALSE);
8735   pic16_aopOp (result,ic,FALSE);
8736
8737   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8738
8739   same = pic16_sameRegs(AOP(result),AOP(left));
8740
8741   /* move it to the result */
8742   size = AOP_SIZE(result);    
8743
8744   /* get the msb and put it into the carry */
8745   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8746
8747   offset = 0 ;
8748
8749   while(size--) {
8750
8751     if(same) {
8752       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8753     } else {
8754       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8755       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8756     }
8757
8758     offset++;
8759   }
8760
8761
8762   pic16_freeAsmop(left,NULL,ic,TRUE);
8763   pic16_freeAsmop(result,NULL,ic,TRUE);
8764 }
8765
8766
8767 /* gpasm can get the highest order bit with HIGH/UPPER
8768  * so the following probably is not needed -- VR */
8769  
8770 /*-----------------------------------------------------------------*/
8771 /* genGetHbit - generates code get highest order bit               */
8772 /*-----------------------------------------------------------------*/
8773 static void genGetHbit (iCode *ic)
8774 {
8775     operand *left, *result;
8776     left = IC_LEFT(ic);
8777     result=IC_RESULT(ic);
8778     pic16_aopOp (left,ic,FALSE);
8779     pic16_aopOp (result,ic,FALSE);
8780
8781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8782     /* get the highest order byte into a */
8783     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8784     if(AOP_TYPE(result) == AOP_CRY){
8785         pic16_emitcode("rlc","a");
8786         pic16_outBitC(result);
8787     }
8788     else{
8789         pic16_emitcode("rl","a");
8790         pic16_emitcode("anl","a,#0x01");
8791         pic16_outAcc(result);
8792     }
8793
8794
8795     pic16_freeAsmop(left,NULL,ic,TRUE);
8796     pic16_freeAsmop(result,NULL,ic,TRUE);
8797 }
8798
8799 #if 0
8800 /*-----------------------------------------------------------------*/
8801 /* AccRol - rotate left accumulator by known count                 */
8802 /*-----------------------------------------------------------------*/
8803 static void AccRol (int shCount)
8804 {
8805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8806     shCount &= 0x0007;              // shCount : 0..7
8807     switch(shCount){
8808         case 0 :
8809             break;
8810         case 1 :
8811             pic16_emitcode("rl","a");
8812             break;
8813         case 2 :
8814             pic16_emitcode("rl","a");
8815             pic16_emitcode("rl","a");
8816             break;
8817         case 3 :
8818             pic16_emitcode("swap","a");
8819             pic16_emitcode("rr","a");
8820             break;
8821         case 4 :
8822             pic16_emitcode("swap","a");
8823             break;
8824         case 5 :
8825             pic16_emitcode("swap","a");
8826             pic16_emitcode("rl","a");
8827             break;
8828         case 6 :
8829             pic16_emitcode("rr","a");
8830             pic16_emitcode("rr","a");
8831             break;
8832         case 7 :
8833             pic16_emitcode("rr","a");
8834             break;
8835     }
8836 }
8837 #endif
8838
8839 /*-----------------------------------------------------------------*/
8840 /* AccLsh - left shift accumulator by known count                  */
8841 /*-----------------------------------------------------------------*/
8842 static void AccLsh (int shCount)
8843 {
8844         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8845         switch(shCount){
8846                 case 0 :
8847                         return;
8848                         break;
8849                 case 1 :
8850                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8851                         break;
8852                 case 2 :
8853                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8854                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8855                         break;
8856                 case 3 :
8857                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8858                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8859                         break;
8860                 case 4 :
8861                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8862                         break;
8863                 case 5 :
8864                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8865                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8866                         break;
8867                 case 6 :
8868                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8869                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8870                         break;
8871                 case 7 :
8872                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8873                         break;
8874         }
8875
8876         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8877 }
8878
8879 /*-----------------------------------------------------------------*/
8880 /* AccRsh - right shift accumulator by known count                 */
8881 /*-----------------------------------------------------------------*/
8882 static void AccRsh (int shCount, int andmask)
8883 {
8884         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8885         switch(shCount){
8886                 case 0 :
8887                         return; break;
8888                 case 1 :
8889                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8890                         break;
8891                 case 2 :
8892                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8893                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8894                         break;
8895                 case 3 :
8896                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8897                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8898                         break;
8899                 case 4 :
8900                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8901                         break;
8902                 case 5 :
8903                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8904                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8905                         break;
8906                 case 6 :
8907                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8908                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8909                         break;
8910                 case 7 :
8911                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8912                         break;
8913         }
8914         
8915         if(andmask)
8916                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8917         else
8918                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8919 }
8920
8921 #if 0
8922 /*-----------------------------------------------------------------*/
8923 /* AccSRsh - signed right shift accumulator by known count                 */
8924 /*-----------------------------------------------------------------*/
8925 static void AccSRsh (int shCount)
8926 {
8927     symbol *tlbl ;
8928     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8929     if(shCount != 0){
8930         if(shCount == 1){
8931             pic16_emitcode("mov","c,acc.7");
8932             pic16_emitcode("rrc","a");
8933         } else if(shCount == 2){
8934             pic16_emitcode("mov","c,acc.7");
8935             pic16_emitcode("rrc","a");
8936             pic16_emitcode("mov","c,acc.7");
8937             pic16_emitcode("rrc","a");
8938         } else {
8939             tlbl = newiTempLabel(NULL);
8940             /* rotate right accumulator */
8941             AccRol(8 - shCount);
8942             /* and kill the higher order bits */
8943             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8944             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8945             pic16_emitcode("orl","a,#0x%02x",
8946                      (unsigned char)~SRMask[shCount]);
8947             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8948         }
8949     }
8950 }
8951 #endif
8952
8953 /*-----------------------------------------------------------------*/
8954 /* shiftR1Left2Result - shift right one byte from left to result   */
8955 /*-----------------------------------------------------------------*/
8956 static void shiftR1Left2ResultSigned (operand *left, int offl,
8957                                 operand *result, int offr,
8958                                 int shCount)
8959 {
8960   int same;
8961
8962   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8963
8964   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8965
8966   switch(shCount) {
8967   case 1:
8968     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8969     if(same) 
8970       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8971     else {
8972       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8973       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8974     }
8975
8976     break;
8977   case 2:
8978
8979     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8980     if(same) 
8981       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8982     else {
8983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8984       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8985     }
8986     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8987     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8988
8989     break;
8990
8991   case 3:
8992     if(same)
8993       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8994     else {
8995       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8996       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8997     }
8998
8999     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9000     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9001     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9002
9003     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9004     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9005
9006     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9007     break;
9008
9009   case 4:
9010     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9011     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
9012     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9013     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
9014     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9015     break;
9016   case 5:
9017     if(same) {
9018       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
9019     } else {
9020       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
9021       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9022     }
9023     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
9024     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
9025     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9026     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
9027     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9028     break;
9029
9030   case 6:
9031     if(same) {
9032       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9033       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9034       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9035       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9036       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9037       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9038     } else {
9039       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9040       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9041       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9042       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9043       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9044     }
9045     break;
9046
9047   case 7:
9048     if(same) {
9049       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9050       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9051       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9052       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9053     } else {
9054       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9055       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9056       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9057     }
9058
9059   default:
9060     break;
9061   }
9062 }
9063
9064 /*-----------------------------------------------------------------*/
9065 /* shiftR1Left2Result - shift right one byte from left to result   */
9066 /*-----------------------------------------------------------------*/
9067 static void shiftR1Left2Result (operand *left, int offl,
9068                                 operand *result, int offr,
9069                                 int shCount, int sign)
9070 {
9071   int same;
9072
9073   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9074
9075   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9076
9077   /* Copy the msb into the carry if signed. */
9078   if(sign) {
9079     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9080     return;
9081   }
9082
9083
9084
9085   switch(shCount) {
9086   case 1:
9087     emitCLRC;
9088     if(same) 
9089       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9090     else {
9091       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9092       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9093     }
9094     break;
9095   case 2:
9096     emitCLRC;
9097     if(same) {
9098       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9099     } else {
9100       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9101       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9102     }
9103     emitCLRC;
9104     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9105
9106     break;
9107   case 3:
9108     if(same)
9109       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9110     else {
9111       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9112       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9113     }
9114
9115     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9116     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9117     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9118     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9119     break;
9120       
9121   case 4:
9122     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9123     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9124     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9125     break;
9126
9127   case 5:
9128     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9129     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9130     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9131     //emitCLRC;
9132     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9133
9134     break;
9135   case 6:
9136
9137     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9138     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9139     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9140     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9141     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9142     break;
9143
9144   case 7:
9145
9146     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9147     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9148     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9149
9150     break;
9151
9152   default:
9153     break;
9154   }
9155 }
9156
9157 /*-----------------------------------------------------------------*/
9158 /* shiftL1Left2Result - shift left one byte from left to result    */
9159 /*-----------------------------------------------------------------*/
9160 static void shiftL1Left2Result (operand *left, int offl,
9161                                 operand *result, int offr, int shCount)
9162 {
9163   int same;
9164
9165   //    char *l;
9166   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9167
9168   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9169   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9170     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9171     //    MOVA(l);
9172     /* shift left accumulator */
9173     //AccLsh(shCount); // don't comment out just yet...
9174   //    pic16_aopPut(AOP(result),"a",offr);
9175
9176   switch(shCount) {
9177   case 1:
9178     /* Shift left 1 bit position */
9179     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9180     if(same) {
9181       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9182     } else {
9183       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9184       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9185     }
9186     break;
9187   case 2:
9188     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9189     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9190     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9191     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9192     break;
9193   case 3:
9194     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9195     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9196     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9197     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9198     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9199     break;
9200   case 4:
9201     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9202     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9203     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9204     break;
9205   case 5:
9206     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9207     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9208     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9210     break;
9211   case 6:
9212     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9213     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9214     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9215     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9216     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9217     break;
9218   case 7:
9219     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9220     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9221     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9222     break;
9223
9224   default:
9225     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9226   }
9227
9228 }
9229
9230 /*-----------------------------------------------------------------*/
9231 /* movLeft2Result - move byte from left to result                  */
9232 /*-----------------------------------------------------------------*/
9233 static void movLeft2Result (operand *left, int offl,
9234                             operand *result, int offr)
9235 {
9236   char *l;
9237   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9238   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9239     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9240
9241     if (*l == '@' && (IS_AOP_PREG(result))) {
9242       pic16_emitcode("mov","a,%s",l);
9243       pic16_aopPut(AOP(result),"a",offr);
9244     } else {
9245       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9246       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9247     }
9248   }
9249 }
9250
9251 /*-----------------------------------------------------------------*/
9252 /* shiftL2Left2Result - shift left two bytes from left to result   */
9253 /*-----------------------------------------------------------------*/
9254 static void shiftL2Left2Result (operand *left, int offl,
9255                                 operand *result, int offr, int shCount)
9256 {
9257   int same = pic16_sameRegs(AOP(result), AOP(left));
9258   int i;
9259
9260   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9261
9262   if (same && (offl != offr)) { // shift bytes
9263     if (offr > offl) {
9264        for(i=1;i>-1;i--) {
9265          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9266          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9267        }
9268     } else { // just treat as different later on
9269                 same = 0;
9270     }
9271   }
9272
9273   if(same) {
9274     switch(shCount) {
9275     case 0:
9276       break;
9277     case 1:
9278     case 2:
9279     case 3:
9280
9281       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9282       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9283       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9284
9285       while(--shCount) {
9286                 emitCLRC;
9287                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9288                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9289       }
9290
9291       break;
9292     case 4:
9293     case 5:
9294       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9295       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9296       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9297       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9298       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9299       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9300       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9301       if(shCount >=5) {
9302                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9303                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9304       }
9305       break;
9306     case 6:
9307       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9308       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9309       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9310       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9311       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9312       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9313       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9314       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9315       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9316       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9317       break;
9318     case 7:
9319       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9320       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9321       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9322       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9323       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9324     }
9325
9326   } else {
9327     switch(shCount) {
9328     case 0:
9329       break;
9330     case 1:
9331     case 2:
9332     case 3:
9333       /* note, use a mov/add for the shift since the mov has a
9334          chance of getting optimized out */
9335       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9336       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9337       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9338       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9339       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9340
9341       while(--shCount) {
9342                 emitCLRC;
9343                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9344                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9345       }
9346       break;
9347
9348     case 4:
9349     case 5:
9350       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9351       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9352       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9353       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9354       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9355       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9356       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9357       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9358
9359
9360       if(shCount == 5) {
9361                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9362                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9363       }
9364       break;
9365     case 6:
9366       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9367       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9368       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9369       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9370
9371       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9372       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9373       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9374       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9375       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9376       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9377       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9378       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9379       break;
9380     case 7:
9381       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9382       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9383       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9384       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9385       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9386     }
9387   }
9388
9389 }
9390 /*-----------------------------------------------------------------*/
9391 /* shiftR2Left2Result - shift right two bytes from left to result  */
9392 /*-----------------------------------------------------------------*/
9393 static void shiftR2Left2Result (operand *left, int offl,
9394                                 operand *result, int offr,
9395                                 int shCount, int sign)
9396 {
9397   int same = pic16_sameRegs(AOP(result), AOP(left));
9398   int i;
9399   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9400
9401   if (same && (offl != offr)) { // shift right bytes
9402     if (offr < offl) {
9403        for(i=0;i<2;i++) {
9404          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9405          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9406        }
9407     } else { // just treat as different later on
9408                 same = 0;
9409     }
9410   }
9411
9412   switch(shCount) {
9413   case 0:
9414     break;
9415   case 1:
9416   case 2:
9417   case 3:
9418     if(sign)
9419       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9420     else
9421       emitCLRC;
9422
9423     if(same) {
9424       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9425       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9426     } else {
9427       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9428       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9429       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9430       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9431     }
9432
9433     while(--shCount) {
9434       if(sign)
9435                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9436       else
9437                 emitCLRC;
9438       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9439       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9440     }
9441     break;
9442   case 4:
9443   case 5:
9444     if(same) {
9445
9446       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9447       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9448       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9449
9450       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9451       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9452       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9453       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9454     } else {
9455       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9456       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9457       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9458
9459       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9460       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9461       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9462       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9463       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9464     }
9465
9466     if(shCount >=5) {
9467       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9468       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9469     }
9470
9471     if(sign) {
9472       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9473       pic16_emitpcode(POC_BTFSC, 
9474                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9475       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9476     }
9477
9478     break;
9479
9480   case 6:
9481     if(same) {
9482
9483       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9484       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9485
9486       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9487       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9488       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9489       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9490       if(sign) {
9491         pic16_emitpcode(POC_BTFSC, 
9492                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9493         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9494       }
9495       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9496       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9497       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9498       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9499     } else {
9500       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9501       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9502       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9503       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9504       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9505       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9506       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9507       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9508       if(sign) {
9509         pic16_emitpcode(POC_BTFSC, 
9510                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9511         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9512       }
9513       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9514       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9515
9516         
9517     }
9518
9519     break;
9520   case 7:
9521     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9522     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9523     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9524     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9525     if(sign) {
9526       emitSKPNC;
9527       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9528     } else 
9529       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9530   }
9531 }
9532
9533
9534 /*-----------------------------------------------------------------*/
9535 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9536 /*-----------------------------------------------------------------*/
9537 static void shiftLLeftOrResult (operand *left, int offl,
9538                                 operand *result, int offr, int shCount)
9539 {
9540     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9541
9542     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9543     /* shift left accumulator */
9544     AccLsh(shCount);
9545     /* or with result */
9546     /* back to result */
9547     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9548 }
9549
9550 /*-----------------------------------------------------------------*/
9551 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9552 /*-----------------------------------------------------------------*/
9553 static void shiftRLeftOrResult (operand *left, int offl,
9554                                 operand *result, int offr, int shCount)
9555 {
9556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9557     
9558     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9559     /* shift right accumulator */
9560     AccRsh(shCount, 1);
9561     /* or with result */
9562     /* back to result */
9563     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9564 }
9565
9566 /*-----------------------------------------------------------------*/
9567 /* genlshOne - left shift a one byte quantity by known count       */
9568 /*-----------------------------------------------------------------*/
9569 static void genlshOne (operand *result, operand *left, int shCount)
9570 {       
9571     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9572     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9573 }
9574
9575 /*-----------------------------------------------------------------*/
9576 /* genlshTwo - left shift two bytes by known amount != 0           */
9577 /*-----------------------------------------------------------------*/
9578 static void genlshTwo (operand *result,operand *left, int shCount)
9579 {
9580     int size;
9581     
9582     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9583     size = pic16_getDataSize(result);
9584
9585     /* if shCount >= 8 */
9586     if (shCount >= 8) {
9587         shCount -= 8 ;
9588
9589         if (size > 1){
9590             if (shCount)
9591                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9592             else 
9593                 movLeft2Result(left, LSB, result, MSB16);
9594         }
9595         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9596     }
9597
9598     /*  1 <= shCount <= 7 */
9599     else {  
9600         if(size == 1)
9601             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9602         else 
9603             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9604     }
9605 }
9606
9607 /*-----------------------------------------------------------------*/
9608 /* shiftLLong - shift left one long from left to result            */
9609 /* offr = LSB or MSB16                                             */
9610 /*-----------------------------------------------------------------*/
9611 static void shiftLLong (operand *left, operand *result, int offr )
9612 {
9613     int size = AOP_SIZE(result);
9614     int same = pic16_sameRegs(AOP(left),AOP(result));
9615         int i;
9616
9617     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9618
9619         if (same && (offr == MSB16)) { //shift one byte
9620                 for(i=size-1;i>=MSB16;i--) {
9621                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9622                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9623                 }
9624         } else {
9625                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9626         }
9627         
9628     if (size > LSB+offr ){
9629                 if (same) {
9630                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9631                 } else {
9632                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9633                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9634                 }
9635          }
9636
9637     if(size > MSB16+offr){
9638                 if (same) {
9639                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9640                 } else {
9641                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9642                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9643                 }
9644     }
9645
9646     if(size > MSB24+offr){
9647                 if (same) {
9648                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9649                 } else {
9650                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9651                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9652                 }
9653     }
9654
9655     if(size > MSB32+offr){
9656                 if (same) {
9657                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9658                 } else {
9659                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9660                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9661                 }
9662     }
9663     if(offr != LSB)
9664                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9665
9666 }
9667
9668 /*-----------------------------------------------------------------*/
9669 /* genlshFour - shift four byte by a known amount != 0             */
9670 /*-----------------------------------------------------------------*/
9671 static void genlshFour (operand *result, operand *left, int shCount)
9672 {
9673     int size;
9674
9675     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9676     size = AOP_SIZE(result);
9677
9678     /* if shifting more that 3 bytes */
9679     if (shCount >= 24 ) {
9680         shCount -= 24;
9681         if (shCount)
9682             /* lowest order of left goes to the highest
9683             order of the destination */
9684             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9685         else
9686             movLeft2Result(left, LSB, result, MSB32);
9687
9688                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9689                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9690                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9691
9692         return;
9693     }
9694
9695     /* more than two bytes */
9696     else if ( shCount >= 16 ) {
9697         /* lower order two bytes goes to higher order two bytes */
9698         shCount -= 16;
9699         /* if some more remaining */
9700         if (shCount)
9701             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9702         else {
9703             movLeft2Result(left, MSB16, result, MSB32);
9704             movLeft2Result(left, LSB, result, MSB24);
9705         }
9706                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9707                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9708         return;
9709     }    
9710
9711     /* if more than 1 byte */
9712     else if ( shCount >= 8 ) {
9713         /* lower order three bytes goes to higher order  three bytes */
9714         shCount -= 8;
9715         if(size == 2){
9716             if(shCount)
9717                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9718             else
9719                 movLeft2Result(left, LSB, result, MSB16);
9720         }
9721         else{   /* size = 4 */
9722             if(shCount == 0){
9723                 movLeft2Result(left, MSB24, result, MSB32);
9724                 movLeft2Result(left, MSB16, result, MSB24);
9725                 movLeft2Result(left, LSB, result, MSB16);
9726                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9727             }
9728             else if(shCount == 1)
9729                 shiftLLong(left, result, MSB16);
9730             else{
9731                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9732                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9733                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9734                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9735             }
9736         }
9737     }
9738
9739     /* 1 <= shCount <= 7 */
9740     else if(shCount <= 3)
9741     { 
9742         shiftLLong(left, result, LSB);
9743         while(--shCount >= 1)
9744             shiftLLong(result, result, LSB);
9745     }
9746     /* 3 <= shCount <= 7, optimize */
9747     else{
9748         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9749         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9750         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9751     }
9752 }
9753
9754 /*-----------------------------------------------------------------*/
9755 /* genLeftShiftLiteral - left shifting by known count              */
9756 /*-----------------------------------------------------------------*/
9757 void pic16_genLeftShiftLiteral (operand *left,
9758                                  operand *right,
9759                                  operand *result,
9760                                  iCode *ic)
9761 {    
9762     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9763     int size;
9764
9765     FENTRY;
9766     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9767     pic16_freeAsmop(right,NULL,ic,TRUE);
9768
9769     pic16_aopOp(left,ic,FALSE);
9770     pic16_aopOp(result,ic,FALSE);
9771
9772     size = getSize(operandType(result));
9773
9774 #if VIEW_SIZE
9775     pic16_emitcode("; shift left ","result %d, left %d",size,
9776              AOP_SIZE(left));
9777 #endif
9778
9779     /* I suppose that the left size >= result size */
9780     if(shCount == 0){
9781         while(size--){
9782             movLeft2Result(left, size, result, size);
9783         }
9784     }
9785
9786     else if(shCount >= (size * 8))
9787         while(size--)
9788             pic16_aopPut(AOP(result),zero,size);
9789     else{
9790         switch (size) {
9791             case 1:
9792                 genlshOne (result,left,shCount);
9793                 break;
9794
9795             case 2:
9796             case 3:
9797                 genlshTwo (result,left,shCount);
9798                 break;
9799
9800             case 4:
9801                 genlshFour (result,left,shCount);
9802                 break;
9803         }
9804     }
9805     pic16_freeAsmop(left,NULL,ic,TRUE);
9806     pic16_freeAsmop(result,NULL,ic,TRUE);
9807 }
9808
9809 /*-----------------------------------------------------------------*
9810  * genMultiAsm - repeat assembly instruction for size of register.
9811  * if endian == 1, then the high byte (i.e base address + size of 
9812  * register) is used first else the low byte is used first;
9813  *-----------------------------------------------------------------*/
9814 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9815 {
9816
9817   int offset = 0;
9818
9819   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9820
9821   if(!reg)
9822     return;
9823
9824   if(!endian) {
9825     endian = 1;
9826   } else {
9827     endian = -1;
9828     offset = size-1;
9829   }
9830
9831   while(size--) {
9832     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9833     offset += endian;
9834   }
9835
9836 }
9837
9838 #if !(USE_GENERIC_SIGNED_SHIFT)
9839 /*-----------------------------------------------------------------*/
9840 /* genLeftShift - generates code for left shifting                 */
9841 /*-----------------------------------------------------------------*/
9842 static void genLeftShift (iCode *ic)
9843 {
9844   operand *left,*right, *result;
9845   int size, offset;
9846 //  char *l;
9847   symbol *tlbl , *tlbl1;
9848   pCodeOp *pctemp;
9849
9850   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9851
9852   right = IC_RIGHT(ic);
9853   left  = IC_LEFT(ic);
9854   result = IC_RESULT(ic);
9855
9856   pic16_aopOp(right,ic,FALSE);
9857
9858   /* if the shift count is known then do it 
9859      as efficiently as possible */
9860   if (AOP_TYPE(right) == AOP_LIT) {
9861     pic16_genLeftShiftLiteral (left,right,result,ic);
9862     return ;
9863   }
9864
9865   /* shift count is unknown then we have to form
9866    * a loop. Get the loop count in WREG : Note: we take
9867    * only the lower order byte since shifting
9868    * more than 32 bits make no sense anyway, ( the
9869    * largest size of an object can be only 32 bits ) */
9870   
9871   pic16_aopOp(left,ic,FALSE);
9872   pic16_aopOp(result,ic,FALSE);
9873
9874   /* now move the left to the result if they are not the
9875    * same, and if size > 1,
9876    * and if right is not same to result (!!!) -- VR */
9877   if (!pic16_sameRegs(AOP(left),AOP(result))
9878       && (AOP_SIZE(result) > 1)) {
9879
9880     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9881
9882     size = AOP_SIZE(result);
9883     offset=0;
9884     while (size--) {
9885
9886 #if 0
9887       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9888       if (*l == '@' && (IS_AOP_PREG(result))) {
9889
9890           pic16_emitcode("mov","a,%s",l);
9891           pic16_aopPut(AOP(result),"a",offset);
9892       } else
9893 #endif
9894       {
9895         /* we don't know if left is a literal or a register, take care -- VR */
9896         mov2f(AOP(result), AOP(left), offset);
9897       }
9898       offset++;
9899     }
9900   }
9901
9902   size = AOP_SIZE(result);
9903
9904   /* if it is only one byte then */
9905   if (size == 1) {
9906     if(optimized_for_speed) {
9907       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9908       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9909       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9910       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9911       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9912       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9913       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9914       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9915       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9916       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9917       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9918       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9919     } else {
9920
9921       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9922
9923       tlbl = newiTempLabel(NULL);
9924
9925 #if 1
9926       /* this is already done, why change it? */
9927       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9928                 mov2f(AOP(result), AOP(left), 0);
9929       }
9930 #endif
9931
9932       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9933       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9934       pic16_emitpLabel(tlbl->key);
9935       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9936       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9937       emitSKPC;
9938       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9939     }
9940     goto release ;
9941   }
9942     
9943   if (pic16_sameRegs(AOP(left),AOP(result))) {
9944
9945     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9946     
9947     tlbl = newiTempLabel(NULL);
9948     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9949     genMultiAsm(POC_RRCF, result, size,1);
9950     pic16_emitpLabel(tlbl->key);
9951     genMultiAsm(POC_RLCF, result, size,0);
9952     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9953     emitSKPC;
9954     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9955     goto release;
9956   }
9957
9958   //tlbl = newiTempLabel(NULL);
9959   //offset = 0 ;   
9960   //tlbl1 = newiTempLabel(NULL);
9961
9962   //reAdjustPreg(AOP(result));    
9963     
9964   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9965   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9966   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9967   //MOVA(l);
9968   //pic16_emitcode("add","a,acc");         
9969   //pic16_aopPut(AOP(result),"a",offset++);
9970   //while (--size) {
9971   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9972   //  MOVA(l);
9973   //  pic16_emitcode("rlc","a");         
9974   //  pic16_aopPut(AOP(result),"a",offset++);
9975   //}
9976   //reAdjustPreg(AOP(result));
9977
9978   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9979   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9980
9981
9982   tlbl = newiTempLabel(NULL);
9983   tlbl1= newiTempLabel(NULL);
9984
9985   size = AOP_SIZE(result);
9986   offset = 1;
9987
9988   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9989
9990   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9991
9992   /* offset should be 0, 1 or 3 */
9993   
9994   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9995   emitSKPNZ;
9996   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9997
9998   pic16_emitpcode(POC_MOVWF, pctemp);
9999
10000
10001   pic16_emitpLabel(tlbl->key);
10002
10003   emitCLRC;
10004   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10005   while(--size)
10006     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10007
10008   pic16_emitpcode(POC_DECFSZ,  pctemp);
10009   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10010   pic16_emitpLabel(tlbl1->key);
10011
10012   pic16_popReleaseTempReg(pctemp,1);
10013
10014
10015  release:
10016   pic16_freeAsmop (right,NULL,ic,TRUE);
10017   pic16_freeAsmop(left,NULL,ic,TRUE);
10018   pic16_freeAsmop(result,NULL,ic,TRUE);
10019 }
10020 #endif
10021
10022
10023 #if 0
10024 #error old code (left here for reference)
10025 /*-----------------------------------------------------------------*/
10026 /* genLeftShift - generates code for left shifting                 */
10027 /*-----------------------------------------------------------------*/
10028 static void genLeftShift (iCode *ic)
10029 {
10030   operand *left,*right, *result;
10031   int size, offset;
10032   char *l;
10033   symbol *tlbl , *tlbl1;
10034   pCodeOp *pctemp;
10035
10036   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10037
10038   right = IC_RIGHT(ic);
10039   left  = IC_LEFT(ic);
10040   result = IC_RESULT(ic);
10041
10042   pic16_aopOp(right,ic,FALSE);
10043
10044   /* if the shift count is known then do it 
10045      as efficiently as possible */
10046   if (AOP_TYPE(right) == AOP_LIT) {
10047     pic16_genLeftShiftLiteral (left,right,result,ic);
10048     return ;
10049   }
10050
10051   /* shift count is unknown then we have to form 
10052      a loop get the loop count in B : Note: we take
10053      only the lower order byte since shifting
10054      more that 32 bits make no sense anyway, ( the
10055      largest size of an object can be only 32 bits ) */  
10056
10057     
10058   pic16_aopOp(left,ic,FALSE);
10059   pic16_aopOp(result,ic,FALSE);
10060
10061   /* now move the left to the result if they are not the
10062      same */
10063   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10064       AOP_SIZE(result) > 1) {
10065
10066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10067
10068     size = AOP_SIZE(result);
10069     offset=0;
10070     while (size--) {
10071       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10072       if (*l == '@' && (IS_AOP_PREG(result))) {
10073
10074         pic16_emitcode("mov","a,%s",l);
10075         pic16_aopPut(AOP(result),"a",offset);
10076       } else {
10077
10078         /* we don't know if left is a literal or a register, take care -- VR */
10079         mov2f(AOP(result), AOP(left), offset);
10080       }
10081       offset++;
10082     }
10083   }
10084
10085   size = AOP_SIZE(result);
10086
10087   /* if it is only one byte then */
10088   if (size == 1) {
10089     if(optimized_for_speed) {
10090       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10091       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10092       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10093       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10094       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10095       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10096       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10097       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10098       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10099       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10100       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10101       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10102     } else {
10103
10104       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10105
10106       tlbl = newiTempLabel(NULL);
10107       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10108                 mov2f(AOP(result), AOP(left), 0);
10109                 
10110 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10111 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10112       }
10113
10114       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10115       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10116       pic16_emitpLabel(tlbl->key);
10117       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10118       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10119       emitSKPC;
10120       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10121     }
10122     goto release ;
10123   }
10124     
10125   if (pic16_sameRegs(AOP(left),AOP(result))) {
10126
10127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10128     
10129     tlbl = newiTempLabel(NULL);
10130     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10131     genMultiAsm(POC_RRCF, result, size,1);
10132     pic16_emitpLabel(tlbl->key);
10133     genMultiAsm(POC_RLCF, result, size,0);
10134     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10135     emitSKPC;
10136     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10137     goto release;
10138   }
10139
10140   //tlbl = newiTempLabel(NULL);
10141   //offset = 0 ;   
10142   //tlbl1 = newiTempLabel(NULL);
10143
10144   //reAdjustPreg(AOP(result));    
10145     
10146   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10147   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10148   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10149   //MOVA(l);
10150   //pic16_emitcode("add","a,acc");         
10151   //pic16_aopPut(AOP(result),"a",offset++);
10152   //while (--size) {
10153   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10154   //  MOVA(l);
10155   //  pic16_emitcode("rlc","a");         
10156   //  pic16_aopPut(AOP(result),"a",offset++);
10157   //}
10158   //reAdjustPreg(AOP(result));
10159
10160   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10161   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10162
10163
10164   tlbl = newiTempLabel(NULL);
10165   tlbl1= newiTempLabel(NULL);
10166
10167   size = AOP_SIZE(result);
10168   offset = 1;
10169
10170   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10171
10172   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10173
10174   /* offset should be 0, 1 or 3 */
10175   
10176   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10177   emitSKPNZ;
10178   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10179
10180   pic16_emitpcode(POC_MOVWF, pctemp);
10181
10182
10183   pic16_emitpLabel(tlbl->key);
10184
10185   emitCLRC;
10186   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10187   while(--size)
10188     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10189
10190   pic16_emitpcode(POC_DECFSZ,  pctemp);
10191   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10192   pic16_emitpLabel(tlbl1->key);
10193
10194   pic16_popReleaseTempReg(pctemp,1);
10195
10196
10197  release:
10198   pic16_freeAsmop (right,NULL,ic,TRUE);
10199   pic16_freeAsmop(left,NULL,ic,TRUE);
10200   pic16_freeAsmop(result,NULL,ic,TRUE);
10201 }
10202 #endif
10203
10204 /*-----------------------------------------------------------------*/
10205 /* genrshOne - right shift a one byte quantity by known count      */
10206 /*-----------------------------------------------------------------*/
10207 static void genrshOne (operand *result, operand *left,
10208                        int shCount, int sign)
10209 {
10210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10211     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10212 }
10213
10214 /*-----------------------------------------------------------------*/
10215 /* genrshTwo - right shift two bytes by known amount != 0          */
10216 /*-----------------------------------------------------------------*/
10217 static void genrshTwo (operand *result,operand *left,
10218                        int shCount, int sign)
10219 {
10220   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10221   /* if shCount >= 8 */
10222   if (shCount >= 8) {
10223     shCount -= 8 ;
10224     if (shCount)
10225       shiftR1Left2Result(left, MSB16, result, LSB,
10226                          shCount, sign);
10227     else
10228       movLeft2Result(left, MSB16, result, LSB);
10229
10230     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10231
10232     if(sign) {
10233       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10234       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10235     }
10236   }
10237
10238   /*  1 <= shCount <= 7 */
10239   else
10240     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10241 }
10242
10243 /*-----------------------------------------------------------------*/
10244 /* shiftRLong - shift right one long from left to result           */
10245 /* offl = LSB or MSB16                                             */
10246 /*-----------------------------------------------------------------*/
10247 static void shiftRLong (operand *left, int offl,
10248                         operand *result, int sign)
10249 {
10250     int size = AOP_SIZE(result);
10251     int same = pic16_sameRegs(AOP(left),AOP(result));
10252     int i;
10253     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10254
10255         if (same && (offl == MSB16)) { //shift one byte right
10256                 for(i=MSB16;i<size;i++) {
10257                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10258                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10259                 }
10260         }
10261
10262     if(sign)
10263                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10264         else
10265                 emitCLRC;
10266
10267         if (same) {
10268                 if (offl == LSB)
10269                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10270         } else {
10271         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10272         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10273         }
10274
10275     if(offl == MSB16) {
10276         /* add sign of "a" */
10277         pic16_addSign(result, MSB32, sign);
10278         }
10279
10280         if (same) {
10281         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10282         } else {
10283         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10284         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10285         }
10286         
10287         if (same) {
10288         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10289         } else {
10290         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10291         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10292         }
10293
10294         if (same) {
10295         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10296         } else {
10297         if(offl == LSB){
10298                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10299                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10300         }
10301         }
10302 }
10303
10304 /*-----------------------------------------------------------------*/
10305 /* genrshFour - shift four byte by a known amount != 0             */
10306 /*-----------------------------------------------------------------*/
10307 static void genrshFour (operand *result, operand *left,
10308                         int shCount, int sign)
10309 {
10310   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10311   /* if shifting more that 3 bytes */
10312   if(shCount >= 24 ) {
10313     shCount -= 24;
10314     if(shCount)
10315       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10316     else
10317       movLeft2Result(left, MSB32, result, LSB);
10318
10319     pic16_addSign(result, MSB16, sign);
10320   }
10321   else if(shCount >= 16){
10322     shCount -= 16;
10323     if(shCount)
10324       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10325     else{
10326       movLeft2Result(left, MSB24, result, LSB);
10327       movLeft2Result(left, MSB32, result, MSB16);
10328     }
10329     pic16_addSign(result, MSB24, sign);
10330   }
10331   else if(shCount >= 8){
10332     shCount -= 8;
10333     if(shCount == 1)
10334       shiftRLong(left, MSB16, result, sign);
10335     else if(shCount == 0){
10336       movLeft2Result(left, MSB16, result, LSB);
10337       movLeft2Result(left, MSB24, result, MSB16);
10338       movLeft2Result(left, MSB32, result, MSB24);
10339       pic16_addSign(result, MSB32, sign);
10340     }
10341     else{ //shcount >= 2
10342       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10343       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10344       /* the last shift is signed */
10345       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10346       pic16_addSign(result, MSB32, sign);
10347     }
10348   }
10349   else{   /* 1 <= shCount <= 7 */
10350     if(shCount <= 2){
10351       shiftRLong(left, LSB, result, sign);
10352       if(shCount == 2)
10353         shiftRLong(result, LSB, result, sign);
10354     }
10355     else{
10356       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10357       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10358       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10359     }
10360   }
10361 }
10362
10363 /*-----------------------------------------------------------------*/
10364 /* genRightShiftLiteral - right shifting by known count            */
10365 /*-----------------------------------------------------------------*/
10366 static void genRightShiftLiteral (operand *left,
10367                                   operand *right,
10368                                   operand *result,
10369                                   iCode *ic,
10370                                   int sign)
10371 {    
10372   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10373   int lsize,res_size;
10374
10375   pic16_freeAsmop(right,NULL,ic,TRUE);
10376
10377   pic16_aopOp(left,ic,FALSE);
10378   pic16_aopOp(result,ic,FALSE);
10379
10380   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10381
10382 #if VIEW_SIZE
10383   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10384                  AOP_SIZE(left));
10385 #endif
10386
10387   lsize = pic16_getDataSize(left);
10388   res_size = pic16_getDataSize(result);
10389   /* test the LEFT size !!! */
10390
10391   /* I suppose that the left size >= result size */
10392   if(shCount == 0){
10393     while(res_size--)
10394       movLeft2Result(left, lsize, result, res_size);
10395   }
10396
10397   else if(shCount >= (lsize * 8)){
10398
10399     if(res_size == 1) {
10400       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10401       if(sign) {
10402         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10403         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10404       }
10405     } else {
10406
10407       if(sign) {
10408         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10409         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10410         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10411         while(res_size--)
10412           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10413
10414       } else {
10415
10416         while(res_size--)
10417           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10418       }
10419     }
10420   } else {
10421
10422     switch (res_size) {
10423     case 1:
10424       genrshOne (result,left,shCount,sign);
10425       break;
10426
10427     case 2:
10428       genrshTwo (result,left,shCount,sign);
10429       break;
10430
10431     case 4:
10432       genrshFour (result,left,shCount,sign);
10433       break;
10434     default :
10435       break;
10436     }
10437
10438   }
10439
10440   pic16_freeAsmop(left,NULL,ic,TRUE);
10441   pic16_freeAsmop(result,NULL,ic,TRUE);
10442 }
10443
10444 #if !(USE_GENERIC_SIGNED_SHIFT)
10445 /*-----------------------------------------------------------------*/
10446 /* genSignedRightShift - right shift of signed number              */
10447 /*-----------------------------------------------------------------*/
10448 static void genSignedRightShift (iCode *ic)
10449 {
10450   operand *right, *left, *result;
10451   int size, offset;
10452   //  char *l;
10453   symbol *tlbl, *tlbl1 ;
10454   pCodeOp *pctemp;
10455
10456   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10457
10458   /* we do it the hard way put the shift count in b
10459      and loop thru preserving the sign */
10460   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10461
10462   right = IC_RIGHT(ic);
10463   left  = IC_LEFT(ic);
10464   result = IC_RESULT(ic);
10465
10466   pic16_aopOp(right,ic,FALSE);  
10467   pic16_aopOp(left,ic,FALSE);
10468   pic16_aopOp(result,ic,FALSE);
10469
10470
10471   if ( AOP_TYPE(right) == AOP_LIT) {
10472     genRightShiftLiteral (left,right,result,ic,1);
10473     return ;
10474   }
10475   /* shift count is unknown then we have to form 
10476      a loop get the loop count in B : Note: we take
10477      only the lower order byte since shifting
10478      more that 32 bits make no sense anyway, ( the
10479      largest size of an object can be only 32 bits ) */  
10480
10481   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10482   //pic16_emitcode("inc","b");
10483   //pic16_freeAsmop (right,NULL,ic,TRUE);
10484   //pic16_aopOp(left,ic,FALSE);
10485   //pic16_aopOp(result,ic,FALSE);
10486
10487   /* now move the left to the result if they are not the
10488      same */
10489   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10490       AOP_SIZE(result) > 1) {
10491
10492     size = AOP_SIZE(result);
10493     offset=0;
10494     while (size--) { 
10495       /*
10496         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10497         if (*l == '@' && IS_AOP_PREG(result)) {
10498
10499         pic16_emitcode("mov","a,%s",l);
10500         pic16_aopPut(AOP(result),"a",offset);
10501         } else
10502         pic16_aopPut(AOP(result),l,offset);
10503       */
10504       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10505       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10506
10507       offset++;
10508     }
10509   }
10510
10511   /* mov the highest order bit to OVR */    
10512   tlbl = newiTempLabel(NULL);
10513   tlbl1= newiTempLabel(NULL);
10514
10515   size = AOP_SIZE(result);
10516   offset = size - 1;
10517
10518   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10519
10520   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10521
10522   /* offset should be 0, 1 or 3 */
10523   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10524   emitSKPNZ;
10525   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10526
10527   pic16_emitpcode(POC_MOVWF, pctemp);
10528
10529
10530   pic16_emitpLabel(tlbl->key);
10531
10532   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10533   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10534
10535   while(--size) {
10536     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10537   }
10538
10539   pic16_emitpcode(POC_DECFSZ,  pctemp);
10540   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10541   pic16_emitpLabel(tlbl1->key);
10542
10543   pic16_popReleaseTempReg(pctemp,1);
10544 #if 0
10545   size = AOP_SIZE(result);
10546   offset = size - 1;
10547   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10548   pic16_emitcode("rlc","a");
10549   pic16_emitcode("mov","ov,c");
10550   /* if it is only one byte then */
10551   if (size == 1) {
10552     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10553     MOVA(l);
10554     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10555     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10556     pic16_emitcode("mov","c,ov");
10557     pic16_emitcode("rrc","a");
10558     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10559     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10560     pic16_aopPut(AOP(result),"a",0);
10561     goto release ;
10562   }
10563
10564   reAdjustPreg(AOP(result));
10565   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10566   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10567   pic16_emitcode("mov","c,ov");
10568   while (size--) {
10569     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10570     MOVA(l);
10571     pic16_emitcode("rrc","a");         
10572     pic16_aopPut(AOP(result),"a",offset--);
10573   }
10574   reAdjustPreg(AOP(result));
10575   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10576   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10577
10578  release:
10579 #endif
10580
10581   pic16_freeAsmop(left,NULL,ic,TRUE);
10582   pic16_freeAsmop(result,NULL,ic,TRUE);
10583   pic16_freeAsmop(right,NULL,ic,TRUE);
10584 }
10585 #endif
10586
10587 #if !(USE_GENERIC_SIGNED_SHIFT)
10588 #warning This implementation of genRightShift() is incomplete!
10589 /*-----------------------------------------------------------------*/
10590 /* genRightShift - generate code for right shifting                */
10591 /*-----------------------------------------------------------------*/
10592 static void genRightShift (iCode *ic)
10593 {
10594     operand *right, *left, *result;
10595     sym_link *letype ;
10596     int size, offset;
10597     char *l;
10598     symbol *tlbl, *tlbl1 ;
10599
10600     /* if signed then we do it the hard way preserve the
10601     sign bit moving it inwards */
10602     letype = getSpec(operandType(IC_LEFT(ic)));
10603     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10604
10605     if (!SPEC_USIGN(letype)) {
10606         genSignedRightShift (ic);
10607         return ;
10608     }
10609
10610     /* signed & unsigned types are treated the same : i.e. the
10611     signed is NOT propagated inwards : quoting from the
10612     ANSI - standard : "for E1 >> E2, is equivalent to division
10613     by 2**E2 if unsigned or if it has a non-negative value,
10614     otherwise the result is implementation defined ", MY definition
10615     is that the sign does not get propagated */
10616
10617     right = IC_RIGHT(ic);
10618     left  = IC_LEFT(ic);
10619     result = IC_RESULT(ic);
10620
10621     pic16_aopOp(right,ic,FALSE);
10622
10623     /* if the shift count is known then do it 
10624     as efficiently as possible */
10625     if (AOP_TYPE(right) == AOP_LIT) {
10626         genRightShiftLiteral (left,right,result,ic, 0);
10627         return ;
10628     }
10629
10630     /* shift count is unknown then we have to form 
10631     a loop get the loop count in B : Note: we take
10632     only the lower order byte since shifting
10633     more that 32 bits make no sense anyway, ( the
10634     largest size of an object can be only 32 bits ) */  
10635
10636     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10637     pic16_emitcode("inc","b");
10638     pic16_aopOp(left,ic,FALSE);
10639     pic16_aopOp(result,ic,FALSE);
10640
10641     /* now move the left to the result if they are not the
10642     same */
10643     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10644         AOP_SIZE(result) > 1) {
10645
10646         size = AOP_SIZE(result);
10647         offset=0;
10648         while (size--) {
10649             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10650             if (*l == '@' && IS_AOP_PREG(result)) {
10651
10652                 pic16_emitcode("mov","a,%s",l);
10653                 pic16_aopPut(AOP(result),"a",offset);
10654             } else
10655                 pic16_aopPut(AOP(result),l,offset);
10656             offset++;
10657         }
10658     }
10659
10660     tlbl = newiTempLabel(NULL);
10661     tlbl1= newiTempLabel(NULL);
10662     size = AOP_SIZE(result);
10663     offset = size - 1;
10664
10665     /* if it is only one byte then */
10666     if (size == 1) {
10667
10668       tlbl = newiTempLabel(NULL);
10669       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10670         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10671         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10672       }
10673
10674       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10675       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10676       pic16_emitpLabel(tlbl->key);
10677       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10678       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10679       emitSKPC;
10680       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10681
10682       goto release ;
10683     }
10684
10685     reAdjustPreg(AOP(result));
10686     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10687     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10688     CLRC;
10689     while (size--) {
10690         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10691         MOVA(l);
10692         pic16_emitcode("rrc","a");         
10693         pic16_aopPut(AOP(result),"a",offset--);
10694     }
10695     reAdjustPreg(AOP(result));
10696
10697     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10698     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10699
10700 release:
10701     pic16_freeAsmop(left,NULL,ic,TRUE);
10702     pic16_freeAsmop (right,NULL,ic,TRUE);
10703     pic16_freeAsmop(result,NULL,ic,TRUE);
10704 }
10705 #endif
10706
10707 #if (USE_GENERIC_SIGNED_SHIFT)
10708 /*-----------------------------------------------------------------*/
10709 /* genGenericShift - generates code for left or right shifting     */
10710 /*-----------------------------------------------------------------*/
10711 static void genGenericShift (iCode *ic, int isShiftLeft) {
10712   operand *left,*right, *result;
10713   int offset;
10714   int sign, signedCount;
10715   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10716   PIC_OPCODE pos_shift, neg_shift;
10717
10718   FENTRY;
10719
10720   right = IC_RIGHT(ic);
10721   left  = IC_LEFT(ic);
10722   result = IC_RESULT(ic);
10723
10724   pic16_aopOp(right,ic,FALSE);
10725   pic16_aopOp(left,ic,FALSE);
10726   pic16_aopOp(result,ic,FALSE);
10727
10728   sign = !SPEC_USIGN(operandType (left));
10729   signedCount = !SPEC_USIGN(operandType (right));
10730
10731   /* if the shift count is known then do it 
10732      as efficiently as possible */
10733   if (AOP_TYPE(right) == AOP_LIT) {
10734     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10735     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10736     // we should modify right->aopu.aop_lit here!
10737     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10738     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10739     if (isShiftLeft)
10740       pic16_genLeftShiftLiteral (left,right,result,ic);
10741     else
10742       genRightShiftLiteral (left,right,result,ic, sign);
10743
10744     goto release;
10745   } // if (right is literal)
10746
10747   /* shift count is unknown then we have to form a loop.
10748    * Note: we take only the lower order byte since shifting
10749    * more than 32 bits make no sense anyway, ( the
10750    * largest size of an object can be only 32 bits )
10751    * Note: we perform arithmetic shifts if the left operand is
10752    * signed and we do an (effective) right shift, i. e. we
10753    * shift in the sign bit from the left. */
10754    
10755   label_complete = newiTempLabel ( NULL );
10756   label_loop_pos = newiTempLabel ( NULL );
10757   label_loop_neg = NULL;
10758   label_negative = NULL;
10759   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10760   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10761
10762   if (signedCount) {
10763     // additional labels needed
10764     label_loop_neg = newiTempLabel ( NULL );
10765     label_negative = newiTempLabel ( NULL );
10766   } // if
10767
10768   // copy source to result -- this will effectively truncate the left operand to the size of result!
10769   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10770   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10771   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10772     mov2f (AOP(result),AOP(left), offset);
10773   } // for
10774
10775   // if result is longer than left, fill with zeros (or sign)
10776   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10777     if (sign && AOP_SIZE(left) > 0) {
10778       // shift signed operand -- fill with sign
10779       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10780       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10781       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10782       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10783         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10784       } // for
10785     } else {
10786       // shift unsigned operand -- fill result with zeros
10787       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10788         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10789       } // for
10790     }
10791   } // if (size mismatch)
10792
10793   pic16_mov2w (AOP(right), 0);
10794   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10795   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10796   
10797 #if 0
10798   // perform a shift by one (shift count is positive)
10799   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10800   // 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])
10801   pic16_emitpLabel (label_loop_pos->key);
10802   emitCLRC;
10803   if (sign && (pos_shift == POC_RRCF)) {
10804     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10805     emitSETC;
10806   } // if
10807   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10808   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10809   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10810 #else
10811   // perform a shift by one (shift count is positive)
10812   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10813   // 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])
10814   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10815   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10816   emitCLRC;
10817   pic16_emitpLabel (label_loop_pos->key);
10818   if (sign && (pos_shift == POC_RRCF)) {
10819     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10820     emitSETC;
10821   } // if
10822   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10823   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10824   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10825   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10826 #endif
10827
10828   if (signedCount) {
10829     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10830
10831     pic16_emitpLabel (label_negative->key);
10832     // perform a shift by -1 (shift count is negative)
10833     // 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)
10834     emitCLRC;
10835     pic16_emitpLabel (label_loop_neg->key);
10836     if (sign && (neg_shift == POC_RRCF)) {
10837       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10838       emitSETC;
10839     } // if
10840     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10841     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10842     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10843     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10844   } // if (signedCount)
10845
10846   pic16_emitpLabel (label_complete->key);
10847
10848 release:
10849   pic16_freeAsmop (right,NULL,ic,TRUE);
10850   pic16_freeAsmop(left,NULL,ic,TRUE);
10851   pic16_freeAsmop(result,NULL,ic,TRUE);
10852 }
10853
10854 static void genLeftShift (iCode *ic) {
10855   genGenericShift (ic, 1);
10856 }
10857
10858 static void genRightShift (iCode *ic) {
10859   genGenericShift (ic, 0);
10860 }
10861 #endif
10862
10863
10864 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10865 void pic16_loadFSR0(operand *op, int lit)
10866 {
10867   if(is_LitOp( op ) || lit) {
10868     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10869   } else {
10870     // set up FSR0 with address of result
10871     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10872     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10873   }
10874 }
10875
10876 /*-----------------------------------------------------------------*/
10877 /* genUnpackBits - generates code for unpacking bits               */
10878 /*-----------------------------------------------------------------*/
10879 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10880 {    
10881   int shCnt ;
10882   int rlen = 0 ;
10883   sym_link *etype, *letype;
10884   int blen=0, bstr=0;
10885   int lbstr;
10886   int offset = 0 ;
10887
10888     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10889     etype = getSpec(operandType(result));
10890     letype = getSpec(operandType(left));
10891     
10892 //    if(IS_BITFIELD(etype)) {
10893       blen = SPEC_BLEN(etype);
10894       bstr = SPEC_BSTR(etype);
10895 //    }
10896
10897     lbstr = SPEC_BSTR( letype );
10898
10899 #if 1
10900     if((blen == 1) && (bstr < 8)) {
10901       /* it is a single bit, so use the appropriate bit instructions */
10902       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10903
10904       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10905       
10906       if((ptype == POINTER) && (result)) {
10907         /* workaround to reduce the extra lfsr instruction */
10908         pic16_emitpcode(POC_BTFSC,
10909               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10910       } else {
10911         pic16_emitpcode(POC_BTFSC,
10912               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10913       }
10914         
10915       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10916
10917       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10918       return;
10919     }
10920
10921 #endif
10922
10923         /* the following call to pic16_loadFSR0 is temporary until
10924          * optimization to handle single bit assignments is added
10925          * to the function. Until then use the old safe way! -- VR */
10926         pic16_loadFSR0( left, 1 );
10927  
10928         /* read the first byte  */
10929         switch (ptype) {
10930                 case POINTER:
10931                 case IPOINTER:
10932                 case PPOINTER:
10933                 case FPOINTER:
10934                 case GPOINTER:
10935                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10936                         break;
10937                 case CPOINTER:
10938                         pic16_emitcode("clr","a");
10939                         pic16_emitcode("movc","a","@a+dptr");
10940                         break;
10941         }
10942         
10943
10944         /* if we have bitdisplacement then it fits   */
10945         /* into this byte completely or if length is */
10946         /* less than a byte                          */
10947         if ((shCnt = SPEC_BSTR(etype)) || 
10948                 (SPEC_BLEN(etype) <= 8))  {
10949
10950                 /* shift right acc */
10951                 AccRsh(shCnt, 0);
10952
10953                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10954                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10955
10956 /* VR -- normally I would use the following, but since we use the hack,
10957  * to avoid the masking from AccRsh, why not mask it right now? */
10958
10959 /*
10960                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10961 */
10962
10963                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10964           return ;
10965         }
10966
10967
10968
10969         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10970         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10971         exit(-1);
10972
10973     /* bit field did not fit in a byte  */
10974     rlen = SPEC_BLEN(etype) - 8;
10975     pic16_aopPut(AOP(result),"a",offset++);
10976
10977     while (1)  {
10978
10979         switch (ptype) {
10980         case POINTER:
10981         case IPOINTER:
10982             pic16_emitcode("inc","%s",rname);
10983             pic16_emitcode("mov","a,@%s",rname);
10984             break;
10985             
10986         case PPOINTER:
10987             pic16_emitcode("inc","%s",rname);
10988             pic16_emitcode("movx","a,@%s",rname);
10989             break;
10990
10991         case FPOINTER:
10992             pic16_emitcode("inc","dptr");
10993             pic16_emitcode("movx","a,@dptr");
10994             break;
10995             
10996         case CPOINTER:
10997             pic16_emitcode("clr","a");
10998             pic16_emitcode("inc","dptr");
10999             pic16_emitcode("movc","a","@a+dptr");
11000             break;
11001             
11002         case GPOINTER:
11003             pic16_emitcode("inc","dptr");
11004             pic16_emitcode("lcall","__gptrget");
11005             break;
11006         }
11007
11008         rlen -= 8;            
11009         /* if we are done */
11010         if ( rlen <= 0 )
11011             break ;
11012         
11013         pic16_aopPut(AOP(result),"a",offset++);
11014                               
11015     }
11016     
11017     if (rlen) {
11018         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11019         pic16_aopPut(AOP(result),"a",offset);          
11020     }
11021     
11022     return ;
11023 }
11024
11025
11026 static void genDataPointerGet(operand *left,
11027                               operand *result,
11028                               iCode *ic)
11029 {
11030   int size, offset = 0, leoffset=0 ;
11031
11032         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11033         pic16_aopOp(result, ic, FALSE);
11034
11035         size = AOP_SIZE(result);
11036 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11037
11038
11039 #if 0
11040         /* The following tests may save a redudant movff instruction when
11041          * accessing unions */
11042          
11043         /* if they are the same */
11044         if (operandsEqu (left, result)) {
11045                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11046                 goto release;
11047         }
11048 #endif
11049
11050 #if 0
11051         /* if they are the same registers */
11052         if (pic16_sameRegs(AOP(left),AOP(result))) {
11053                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11054                 goto release;
11055         }
11056 #endif
11057
11058 #if 1
11059         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11060                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11061                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11062                 goto release;
11063         }
11064 #endif
11065
11066
11067 #if 0
11068         if ( AOP_TYPE(left) == AOP_PCODE) {
11069                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11070                                 AOP(left)->aopu.pcop->name,
11071                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11072                                 PCOR(AOP(left)->aopu.pcop)->instance:
11073                                 PCOI(AOP(left)->aopu.pcop)->offset);
11074         }
11075 #endif
11076
11077         if(AOP(left)->aopu.pcop->type == PO_DIR)
11078                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11079
11080         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11081
11082         while (size--) {
11083                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11084                 
11085                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11086                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11087                         pic16_mov2w(AOP(left), offset); // patch 8
11088                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11089                 } else {
11090                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11091                                 pic16_popGet(AOP(left), offset), //patch 8
11092                                 pic16_popGet(AOP(result), offset)));
11093                 }
11094
11095                 offset++;
11096                 leoffset++;
11097         }
11098
11099 release:
11100     pic16_freeAsmop(result,NULL,ic,TRUE);
11101 }
11102
11103
11104
11105 /*-----------------------------------------------------------------*/
11106 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11107 /*-----------------------------------------------------------------*/
11108 static void genNearPointerGet (operand *left, 
11109                                operand *result, 
11110                                iCode *ic)
11111 {
11112 //  asmop *aop = NULL;
11113   //regs *preg = NULL ;
11114   sym_link *rtype, *retype;
11115   sym_link *ltype = operandType(left);    
11116
11117     FENTRY;
11118     
11119     rtype = operandType(result);
11120     retype= getSpec(rtype);
11121     
11122     pic16_aopOp(left,ic,FALSE);
11123
11124 //    pic16_DumpOp("(left)",left);
11125 //    pic16_DumpOp("(result)",result);
11126
11127     /* if left is rematerialisable and
11128      * result is not bit variable type and
11129      * the left is pointer to data space i.e
11130      * lower 128 bytes of space */
11131     
11132     if (AOP_TYPE(left) == AOP_PCODE
11133       && !IS_BITFIELD(retype)
11134       && DCL_TYPE(ltype) == POINTER) {
11135
11136         genDataPointerGet (left,result,ic);
11137         pic16_freeAsmop(left, NULL, ic, TRUE);
11138         return ;
11139     }
11140     
11141     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11142     pic16_aopOp (result,ic,FALSE);
11143     
11144     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11145
11146 #if 1
11147     if(IS_BITFIELD( retype )
11148       && (SPEC_BLEN(operandType(result))==1)
11149     ) {
11150       iCode *nextic;
11151       pCodeOp *jop;
11152       int bitstrt, bytestrt;
11153
11154         /* if this is bitfield of size 1, see if we are checking the value
11155          * of a single bit in an if-statement,
11156          * if yes, then don't generate usual code, but execute the
11157          * genIfx directly -- VR */
11158
11159         nextic = ic->next;
11160
11161         /* CHECK: if next iCode is IFX
11162          * and current result operand is nextic's conditional operand
11163          * and current result operand live ranges ends at nextic's key number
11164          */
11165         if((nextic->op == IFX)
11166           && (result == IC_COND(nextic))
11167           && (OP_LIVETO(result) == nextic->seq)
11168           ) {
11169             /* everything is ok then */
11170             /* find a way to optimize the genIfx iCode */
11171
11172             bytestrt = SPEC_BSTR(operandType(result))/8;
11173             bitstrt = SPEC_BSTR(operandType(result))%8;
11174             
11175             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11176
11177             genIfxpCOpJump(nextic, jop);
11178             
11179             pic16_freeAsmop(left, NULL, ic, TRUE);
11180             pic16_freeAsmop(result, NULL, ic, TRUE);
11181             return;
11182         }
11183     }
11184 #endif
11185
11186
11187     /* if the value is already in a pointer register
11188      * then don't need anything more */
11189     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11190       /* otherwise get a free pointer register */
11191       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11192                 
11193       ;
11194     }
11195
11196     /* if bitfield then unpack the bits */
11197     if (IS_BITFIELD(retype)) 
11198       genUnpackBits (result, left, NULL, POINTER);
11199     else {
11200       /* we have can just get the values */
11201       int size = AOP_SIZE(result);
11202       int offset = 0;   
11203         
11204       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11205
11206       pic16_loadFSR0( left, 0 );
11207
11208       while(size--) {
11209         if(size) {
11210           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11211                 pic16_popGet(AOP(result), offset++)));
11212         } else {
11213           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11214                 pic16_popGet(AOP(result), offset++)));
11215         }
11216       }
11217     }
11218
11219 #if 0
11220     /* now some housekeeping stuff */
11221     if (aop) {
11222       /* we had to allocate for this iCode */
11223       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11224       pic16_freeAsmop(NULL,aop,ic,TRUE);
11225     } else { 
11226       /* we did not allocate which means left
11227        * already in a pointer register, then
11228        * if size > 0 && this could be used again
11229        * we have to point it back to where it 
11230        * belongs */
11231       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11232       if (AOP_SIZE(result) > 1
11233         && !OP_SYMBOL(left)->remat
11234         && ( OP_SYMBOL(left)->liveTo > ic->seq
11235             || ic->depth )) {
11236 //        int size = AOP_SIZE(result) - 1;
11237 //        while (size--)
11238 //          pic16_emitcode("dec","%s",rname);
11239         }
11240     }
11241 #endif
11242
11243     /* done */
11244     pic16_freeAsmop(left,NULL,ic,TRUE);
11245     pic16_freeAsmop(result,NULL,ic,TRUE);
11246 }
11247
11248 /*-----------------------------------------------------------------*/
11249 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11250 /*-----------------------------------------------------------------*/
11251 static void genPagedPointerGet (operand *left, 
11252                                operand *result, 
11253                                iCode *ic)
11254 {
11255     asmop *aop = NULL;
11256     regs *preg = NULL ;
11257     char *rname ;
11258     sym_link *rtype, *retype;    
11259
11260     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11261
11262     rtype = operandType(result);
11263     retype= getSpec(rtype);
11264     
11265     pic16_aopOp(left,ic,FALSE);
11266
11267   /* if the value is already in a pointer register
11268        then don't need anything more */
11269     if (!AOP_INPREG(AOP(left))) {
11270         /* otherwise get a free pointer register */
11271         aop = newAsmop(0);
11272         preg = getFreePtr(ic,&aop,FALSE);
11273         pic16_emitcode("mov","%s,%s",
11274                 preg->name,
11275                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11276         rname = preg->name ;
11277     } else
11278         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11279     
11280     pic16_freeAsmop(left,NULL,ic,TRUE);
11281     pic16_aopOp (result,ic,FALSE);
11282
11283     /* if bitfield then unpack the bits */
11284     if (IS_BITFIELD(retype)) 
11285         genUnpackBits (result,left,rname,PPOINTER);
11286     else {
11287         /* we have can just get the values */
11288         int size = AOP_SIZE(result);
11289         int offset = 0 ;        
11290         
11291         while (size--) {
11292             
11293             pic16_emitcode("movx","a,@%s",rname);
11294             pic16_aopPut(AOP(result),"a",offset);
11295             
11296             offset++ ;
11297             
11298             if (size)
11299                 pic16_emitcode("inc","%s",rname);
11300         }
11301     }
11302
11303     /* now some housekeeping stuff */
11304     if (aop) {
11305         /* we had to allocate for this iCode */
11306         pic16_freeAsmop(NULL,aop,ic,TRUE);
11307     } else { 
11308         /* we did not allocate which means left
11309            already in a pointer register, then
11310            if size > 0 && this could be used again
11311            we have to point it back to where it 
11312            belongs */
11313         if (AOP_SIZE(result) > 1 &&
11314             !OP_SYMBOL(left)->remat &&
11315             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11316               ic->depth )) {
11317             int size = AOP_SIZE(result) - 1;
11318             while (size--)
11319                 pic16_emitcode("dec","%s",rname);
11320         }
11321     }
11322
11323     /* done */
11324     pic16_freeAsmop(result,NULL,ic,TRUE);
11325     
11326         
11327 }
11328
11329 /*-----------------------------------------------------------------*/
11330 /* genFarPointerGet - gget value from far space                    */
11331 /*-----------------------------------------------------------------*/
11332 static void genFarPointerGet (operand *left,
11333                               operand *result, iCode *ic)
11334 {
11335     int size, offset ;
11336     sym_link *retype = getSpec(operandType(result));
11337
11338     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11339
11340     pic16_aopOp(left,ic,FALSE);
11341
11342     /* if the operand is already in dptr 
11343     then we do nothing else we move the value to dptr */
11344     if (AOP_TYPE(left) != AOP_STR) {
11345         /* if this is remateriazable */
11346         if (AOP_TYPE(left) == AOP_IMMD)
11347             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11348         else { /* we need to get it byte by byte */
11349             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11350             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11351             if (options.model == MODEL_FLAT24)
11352             {
11353                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11354             }
11355         }
11356     }
11357     /* so dptr know contains the address */
11358     pic16_freeAsmop(left,NULL,ic,TRUE);
11359     pic16_aopOp(result,ic,FALSE);
11360
11361     /* if bit then unpack */
11362     if (IS_BITFIELD(retype)) 
11363         genUnpackBits(result,left,"dptr",FPOINTER);
11364     else {
11365         size = AOP_SIZE(result);
11366         offset = 0 ;
11367
11368         while (size--) {
11369             pic16_emitcode("movx","a,@dptr");
11370             pic16_aopPut(AOP(result),"a",offset++);
11371             if (size)
11372                 pic16_emitcode("inc","dptr");
11373         }
11374     }
11375
11376     pic16_freeAsmop(result,NULL,ic,TRUE);
11377 }
11378
11379 #if 0
11380 /*-----------------------------------------------------------------*/
11381 /* genCodePointerGet - get value from code space                  */
11382 /*-----------------------------------------------------------------*/
11383 static void genCodePointerGet (operand *left,
11384                                 operand *result, iCode *ic)
11385 {
11386     int size, offset ;
11387     sym_link *retype = getSpec(operandType(result));
11388
11389     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11390
11391     pic16_aopOp(left,ic,FALSE);
11392
11393     /* if the operand is already in dptr 
11394     then we do nothing else we move the value to dptr */
11395     if (AOP_TYPE(left) != AOP_STR) {
11396         /* if this is remateriazable */
11397         if (AOP_TYPE(left) == AOP_IMMD)
11398             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11399         else { /* we need to get it byte by byte */
11400             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11401             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11402             if (options.model == MODEL_FLAT24)
11403             {
11404                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11405             }
11406         }
11407     }
11408     /* so dptr know contains the address */
11409     pic16_freeAsmop(left,NULL,ic,TRUE);
11410     pic16_aopOp(result,ic,FALSE);
11411
11412     /* if bit then unpack */
11413     if (IS_BITFIELD(retype)) 
11414         genUnpackBits(result,left,"dptr",CPOINTER);
11415     else {
11416         size = AOP_SIZE(result);
11417         offset = 0 ;
11418
11419         while (size--) {
11420             pic16_emitcode("clr","a");
11421             pic16_emitcode("movc","a,@a+dptr");
11422             pic16_aopPut(AOP(result),"a",offset++);
11423             if (size)
11424                 pic16_emitcode("inc","dptr");
11425         }
11426     }
11427
11428     pic16_freeAsmop(result,NULL,ic,TRUE);
11429 }
11430 #endif
11431
11432 #if 0
11433 /*-----------------------------------------------------------------*/
11434 /* genGenPointerGet - gget value from generic pointer space        */
11435 /*-----------------------------------------------------------------*/
11436 static void genGenPointerGet (operand *left,
11437                               operand *result, iCode *ic)
11438 {
11439   int size, offset, lit;
11440   sym_link *retype = getSpec(operandType(result));
11441
11442         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11443         pic16_aopOp(left,ic,FALSE);
11444         pic16_aopOp(result,ic,FALSE);
11445         size = AOP_SIZE(result);
11446
11447         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11448
11449         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11450
11451                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11452                 // load FSR0 from immediate
11453                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11454
11455 //              pic16_loadFSR0( left );
11456
11457                 offset = 0;
11458                 while(size--) {
11459                         if(size) {
11460                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11461                         } else {
11462                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11463                         }
11464                         offset++;
11465                 }
11466                 goto release;
11467
11468         }
11469         else { /* we need to get it byte by byte */
11470                 // set up FSR0 with address from left
11471                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11472                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11473                 
11474                 offset = 0 ;
11475
11476                 while(size--) {
11477                         if(size) {
11478                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11479                         } else {
11480                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11481                         }
11482                         offset++;
11483                 }
11484                 goto release;
11485         }
11486
11487   /* if bit then unpack */
11488         if (IS_BITFIELD(retype)) 
11489                 genUnpackBits(result,left,"BAD",GPOINTER);
11490
11491         release:
11492         pic16_freeAsmop(left,NULL,ic,TRUE);
11493         pic16_freeAsmop(result,NULL,ic,TRUE);
11494
11495 }
11496 #endif
11497
11498
11499 /*-----------------------------------------------------------------*/
11500 /* genGenPointerGet - gget value from generic pointer space        */
11501 /*-----------------------------------------------------------------*/
11502 static void genGenPointerGet (operand *left,
11503                               operand *result, iCode *ic)
11504 {
11505   int size, offset, lit;
11506   sym_link *retype = getSpec(operandType(result));
11507   char fgptrget[32];
11508
11509     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11510     pic16_aopOp(left,ic,FALSE);
11511     pic16_aopOp(result,ic,FALSE);
11512     size = AOP_SIZE(result);
11513
11514     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11515
11516     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11517
11518       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11519       // load FSR0 from immediate
11520       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11521
11522       werror(W_POSSBUG2, __FILE__, __LINE__);
11523
11524       offset = 0;
11525       while(size--) {
11526         if(size) {
11527           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11528         } else {
11529           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11530         }
11531         offset++;
11532       }
11533
11534       goto release;
11535
11536     } else { /* we need to get it byte by byte */
11537
11538       /* set up WREG:PRODL:FSR0L with address from left */
11539       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11540       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11541       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11542       
11543       switch( size ) {
11544         case 1: strcpy(fgptrget, "__gptrget1"); break;
11545         case 2: strcpy(fgptrget, "__gptrget2"); break;
11546         case 3: strcpy(fgptrget, "__gptrget3"); break;
11547         case 4: strcpy(fgptrget, "__gptrget4"); break;
11548         default:
11549           werror(W_POSSBUG2, __FILE__, __LINE__);
11550           abort();
11551       }
11552       
11553       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11554       
11555       assignResultValue(result, 1);
11556       
11557       {
11558         symbol *sym;
11559
11560           sym = newSymbol( fgptrget, 0 );
11561           sym->used++;
11562           strcpy(sym->rname, fgptrget);
11563           checkAddSym(&externs, sym);
11564
11565 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11566       }
11567               
11568       goto release;
11569     }
11570
11571   /* if bit then unpack */
11572     if (IS_BITFIELD(retype)) 
11573       genUnpackBits(result,left,"BAD",GPOINTER);
11574
11575 release:
11576   pic16_freeAsmop(left,NULL,ic,TRUE);
11577   pic16_freeAsmop(result,NULL,ic,TRUE);
11578 }
11579
11580 /*-----------------------------------------------------------------*/
11581 /* genConstPointerGet - get value from const generic pointer space */
11582 /*-----------------------------------------------------------------*/
11583 static void genConstPointerGet (operand *left,
11584                                 operand *result, iCode *ic)
11585 {
11586   //sym_link *retype = getSpec(operandType(result));
11587   // symbol *albl = newiTempLabel(NULL);        // patch 15
11588   // symbol *blbl = newiTempLabel(NULL);        //
11589   // PIC_OPCODE poc;                            // patch 15
11590   int size;
11591   int offset = 0;
11592
11593   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11594   pic16_aopOp(left,ic,FALSE);
11595   pic16_aopOp(result,ic,TRUE);
11596   size = AOP_SIZE(result);
11597
11598   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11599
11600   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11601
11602   // set up table pointer
11603   if( (AOP_TYPE(left) == AOP_PCODE) 
11604       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11605           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11606     {
11607       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11608       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11609       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11610       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11611       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11612       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11613   } else {
11614     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11615     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11616     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11617   }
11618
11619   while(size--) {
11620     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11621     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11622     offset++;
11623   }
11624     
11625   pic16_freeAsmop(left,NULL,ic,TRUE);
11626   pic16_freeAsmop(result,NULL,ic,TRUE);
11627 }
11628
11629
11630 /*-----------------------------------------------------------------*/
11631 /* genPointerGet - generate code for pointer get                   */
11632 /*-----------------------------------------------------------------*/
11633 static void genPointerGet (iCode *ic)
11634 {
11635   operand *left, *result ;
11636   sym_link *type, *etype;
11637   int p_type;
11638
11639     FENTRY;
11640     
11641     left = IC_LEFT(ic);
11642     result = IC_RESULT(ic) ;
11643
11644     /* depending on the type of pointer we need to
11645     move it to the correct pointer register */
11646     type = operandType(left);
11647     etype = getSpec(type);
11648
11649 #if 0
11650     if (IS_PTR_CONST(type))
11651 #else
11652     if (IS_CODEPTR(type))
11653 #endif
11654       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11655
11656     /* if left is of type of pointer then it is simple */
11657     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11658       p_type = DCL_TYPE(type);
11659     else {
11660       /* we have to go by the storage class */
11661       p_type = PTR_TYPE(SPEC_OCLS(etype));
11662
11663       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11664
11665       if (SPEC_OCLS(etype)->codesp ) {
11666         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11667         //p_type = CPOINTER ;   
11668       } else
11669       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11670         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11671         /*p_type = FPOINTER ;*/ 
11672       } else
11673       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11674         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11675         /* p_type = PPOINTER; */
11676       } else
11677       if (SPEC_OCLS(etype) == idata ) {
11678         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11679         /* p_type = IPOINTER; */
11680       } else {
11681         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11682         /* p_type = POINTER ; */
11683       }
11684     }
11685
11686     /* now that we have the pointer type we assign
11687     the pointer values */
11688     switch (p_type) {
11689       case POINTER:     
11690       case IPOINTER:
11691         genNearPointerGet (left,result,ic);
11692         break;
11693
11694       case PPOINTER:
11695         genPagedPointerGet(left,result,ic);
11696         break;
11697
11698       case FPOINTER:
11699         genFarPointerGet (left,result,ic);
11700         break;
11701
11702       case CPOINTER:
11703         genConstPointerGet (left,result,ic);
11704         //pic16_emitcodePointerGet (left,result,ic);
11705         break;
11706
11707       case GPOINTER:
11708 #if 0
11709       if (IS_PTR_CONST(type))
11710         genConstPointerGet (left,result,ic);
11711       else
11712 #endif
11713         genGenPointerGet (left,result,ic);
11714       break;
11715
11716     default:
11717       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11718               "genPointerGet: illegal pointer type");
11719     
11720     }
11721 }
11722
11723 /*-----------------------------------------------------------------*/
11724 /* genPackBits - generates code for packed bit storage             */
11725 /*-----------------------------------------------------------------*/
11726 static void genPackBits (sym_link    *etype , operand *result,
11727                          operand *right ,
11728                          char *rname, int p_type)
11729 {
11730   int shCnt = 0 ;
11731   int offset = 0  ;
11732   int rLen = 0 ;
11733   int blen, bstr ;   
11734   sym_link *retype;
11735
11736         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11737         blen = SPEC_BLEN(etype);
11738         bstr = SPEC_BSTR(etype);
11739
11740         retype = getSpec(operandType(right));
11741
11742         if(AOP_TYPE(right) == AOP_LIT) {
11743                 if((blen == 1) && (bstr < 8)) {
11744                   unsigned long lit;
11745                         /* it is a single bit, so use the appropriate bit instructions */
11746
11747                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11748
11749                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11750 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11751                         if((p_type == POINTER) && (result)) {
11752                                 /* workaround to reduce the extra lfsr instruction */
11753                                 if(lit) {
11754                                         pic16_emitpcode(POC_BSF,
11755                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11756                                 } else {
11757                                         pic16_emitpcode(POC_BCF,
11758                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11759                                 }
11760                         } else {
11761                                 pic16_loadFSR0(result, 1);
11762                                 if(lit) {
11763                                         pic16_emitpcode(POC_BSF,
11764                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11765                                 } else {
11766                                         pic16_emitpcode(POC_BCF,
11767                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11768                                 }
11769                         }
11770         
11771                   return;
11772                 }
11773                 /* move literal to W */
11774                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11775                 offset++;
11776         } else
11777         if(IS_BITFIELD(retype) 
11778           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11779           && (blen == 1)) {
11780           int rblen, rbstr;
11781
11782             rblen = SPEC_BLEN( retype );
11783             rbstr = SPEC_BSTR( retype );
11784             
11785
11786             if(IS_BITFIELD(etype)) {
11787               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11788               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11789             } else {
11790               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11791             }
11792             
11793             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11794             
11795             if(IS_BITFIELD(etype)) {
11796               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11797             } else {
11798               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11799             }
11800
11801             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11802             
11803             return;
11804         } else {
11805           /* move right to W */
11806           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11807         }
11808
11809         /* if the bit length is less than or   */
11810         /* it exactly fits a byte then         */
11811         if((shCnt=SPEC_BSTR(etype))
11812                 || SPEC_BLEN(etype) <= 8 )  {
11813                 int fsr0_setup = 0;
11814
11815                 if (blen != 8 || bstr != 0) {
11816                   // we need to combine the value with the old value
11817                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11818
11819           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11820                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11821                 
11822                   /* shift left acc */
11823                   AccLsh(shCnt);
11824
11825                   /* using PRODH as a temporary register here */
11826                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11827
11828                   /* get old value */
11829                   switch (p_type) {
11830                         case FPOINTER:
11831                         case POINTER:
11832                                 pic16_loadFSR0( result, 1 );
11833                                 fsr0_setup = 1;
11834                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11835 //                              pic16_emitcode ("mov","b,a");
11836 //                              pic16_emitcode("mov","a,@%s",rname);
11837                                 break;
11838
11839                         case GPOINTER:
11840                                 if (AOP(result)->aopu.aop_reg[2]) {
11841                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11842                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11843                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11844                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11845                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11846                                   {
11847                                     symbol *sym;
11848                                     sym = newSymbol( "__gptrget1", 0 );
11849                                     strcpy(sym->rname, "__gptrget1");
11850                                     checkAddSym(&externs, sym);
11851                                   }
11852                                 } else {
11853                                   // data pointer (just 2 byte given)
11854                                   pic16_loadFSR0( result, 1 );
11855                                   fsr0_setup = 1;
11856                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11857                                 }
11858                                 
11859                                 // warnings will be emitted below
11860                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11861                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11862                                 break;
11863
11864                         default:
11865                                 assert (0 && "invalid pointer type specified");
11866                                 break;
11867                   }
11868 #if 1
11869                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11870                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11871                                         (unsigned char)(0xff >> (8-bstr))) ));
11872                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11873                 } // if (blen != 8 || bstr != 0)
11874
11875                 /* write new value back */
11876                 switch (p_type) {
11877                         case FPOINTER:
11878                         case POINTER:
11879                                 if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11880                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11881                                 break;
11882
11883                         case GPOINTER:
11884                                 if (AOP(result)->aopu.aop_reg[2]) {
11885                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11886                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11887                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11888                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11889                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11890                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11891                                   {
11892                                     symbol *sym;
11893                                     sym = newSymbol( "__gptrput1", 0 );
11894                                     strcpy(sym->rname, "__gptrput1");
11895                                     checkAddSym(&externs, sym);
11896                                   }
11897                                 } else {
11898                                   // data pointer (just 2 byte given)
11899                                   if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11900                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11901                                 }
11902                                 
11903                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11904                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11905                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11906                                 break;
11907
11908                         default:
11909                                 assert (0 && "invalid pointer type specified");
11910                                 break;
11911                 }
11912 #endif
11913
11914           return;
11915         }
11916
11917
11918 #if 0
11919         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11920         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11921         exit(-1);
11922 #endif
11923
11924
11925     pic16_loadFSR0(result, 1);                  // load FSR0 with address of result
11926     rLen = SPEC_BLEN(etype)-8;
11927     
11928     /* now generate for lengths greater than one byte */
11929     while (1) {
11930         rLen -= 8 ;
11931         if (rLen <= 0 ) {
11932           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11933           break ;
11934         }
11935
11936         switch (p_type) {
11937             case POINTER:
11938                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11939                 break;
11940
11941 /*
11942             case FPOINTER:
11943                 MOVA(l);
11944                 pic16_emitcode("movx","@dptr,a");
11945                 break;
11946
11947             case GPOINTER:
11948                 MOVA(l);
11949                 DEBUGpic16_emitcode(";lcall","__gptrput");
11950                 break;  
11951 */
11952           default:
11953             assert(0);
11954         }   
11955
11956
11957         pic16_mov2w(AOP(right), offset++);
11958     }
11959
11960     /* last last was not complete */
11961     if (rLen)   {
11962         /* save the byte & read byte */
11963         switch (p_type) {
11964             case POINTER:
11965 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11966                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11967                 break;
11968
11969 /*
11970             case FPOINTER:
11971                 pic16_emitcode ("mov","b,a");
11972                 pic16_emitcode("movx","a,@dptr");
11973                 break;
11974
11975             case GPOINTER:
11976                 pic16_emitcode ("push","b");
11977                 pic16_emitcode ("push","acc");
11978                 pic16_emitcode ("lcall","__gptrget");
11979                 pic16_emitcode ("pop","b");
11980                 break;
11981 */
11982             default:
11983               assert(0);
11984         }
11985         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11986         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11987         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11988 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11989 //        pic16_emitcode ("orl","a,b");
11990     }
11991
11992 //    if (p_type == GPOINTER)
11993 //        pic16_emitcode("pop","b");
11994
11995     switch (p_type) {
11996
11997       case POINTER:
11998         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11999 //      pic16_emitcode("mov","@%s,a",rname);
12000         break;
12001 /*
12002       case FPOINTER:
12003         pic16_emitcode("movx","@dptr,a");
12004         break;
12005         
12006       case GPOINTER:
12007         DEBUGpic16_emitcode(";lcall","__gptrput");
12008         break;                  
12009 */
12010       default:
12011         assert(0);
12012     }
12013     
12014 //    pic16_freeAsmop(right, NULL, ic, TRUE);
12015 }
12016 /*-----------------------------------------------------------------*/
12017 /* genDataPointerSet - remat pointer to data space                 */
12018 /*-----------------------------------------------------------------*/
12019 static void genDataPointerSet(operand *right,
12020                               operand *result,
12021                               iCode *ic)
12022 {
12023     int size, offset = 0, resoffset=0 ;
12024
12025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12026     pic16_aopOp(right,ic,FALSE);
12027
12028     size = AOP_SIZE(right);
12029
12030 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12031
12032 #if 0
12033     if ( AOP_TYPE(result) == AOP_PCODE) {
12034       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12035               AOP(result)->aopu.pcop->name,
12036                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12037               PCOR(AOP(result)->aopu.pcop)->instance:
12038               PCOI(AOP(result)->aopu.pcop)->offset);
12039     }
12040 #endif
12041
12042         if(AOP(result)->aopu.pcop->type == PO_DIR)
12043                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12044
12045         while (size--) {
12046                 if (AOP_TYPE(right) == AOP_LIT) {
12047                   unsigned int lit;
12048
12049                     if(!IS_FLOAT(operandType( right )))
12050                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12051                     else {
12052                       union {
12053                         unsigned long lit_int;
12054                         float lit_float;
12055                       } info;
12056         
12057                         /* take care if literal is a float */
12058                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12059                         lit = info.lit_int;
12060                     }
12061
12062                     lit = lit >> (8*offset);
12063                     if(lit&0xff) {
12064                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12065                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12066                     } else {
12067                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12068                     }
12069                 } else {
12070                   pic16_mov2w(AOP(right), offset);
12071                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12072                 }
12073                 offset++;
12074                 resoffset++;
12075         }
12076
12077     pic16_freeAsmop(right,NULL,ic,TRUE);
12078 }
12079
12080
12081
12082 /*-----------------------------------------------------------------*/
12083 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12084 /*-----------------------------------------------------------------*/
12085 static void genNearPointerSet (operand *right,
12086                                operand *result, 
12087                                iCode *ic)
12088 {
12089   asmop *aop = NULL;
12090   sym_link *retype;
12091   sym_link *ptype = operandType(result);
12092   sym_link *resetype;
12093     
12094         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12095         retype= getSpec(operandType(right));
12096         resetype = getSpec(operandType(result));
12097   
12098         pic16_aopOp(result,ic,FALSE);
12099     
12100         /* if the result is rematerializable &
12101          * in data space & not a bit variable */
12102         
12103         /* and result is not a bit variable */
12104         if (AOP_TYPE(result) == AOP_PCODE
12105 //              && AOP_TYPE(result) == AOP_IMMD
12106                 && DCL_TYPE(ptype) == POINTER
12107                 && !IS_BITFIELD(retype)
12108                 && !IS_BITFIELD(resetype)) {
12109
12110                 genDataPointerSet (right,result,ic);
12111                 pic16_freeAsmop(result,NULL,ic,TRUE);
12112           return;
12113         }
12114
12115         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12116         pic16_aopOp(right,ic,FALSE);
12117         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12118
12119         /* if the value is already in a pointer register
12120          * then don't need anything more */
12121         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12122           /* otherwise get a free pointer register */
12123           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12124
12125           ;
12126         }
12127
12128         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12129
12130         /* if bitfield then unpack the bits */
12131         if (IS_BITFIELD(resetype)) {
12132                 genPackBits (resetype, result, right, NULL, POINTER);
12133         } else {
12134                 /* we have can just get the values */
12135           int size = AOP_SIZE(right);
12136           int offset = 0 ;    
12137
12138             pic16_loadFSR0(result, 0);
12139             
12140                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12141                 while (size--) {
12142                                 if (AOP_TYPE(right) == AOP_LIT) {
12143                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12144                                         if (size) {
12145                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12146                                         } else {
12147                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12148                                         }
12149                                 } else { // no literal
12150                                         if(size) {
12151                                                 pic16_emitpcode(POC_MOVFF,
12152                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12153                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12154                                         } else {
12155                                                 pic16_emitpcode(POC_MOVFF,
12156                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12157                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12158                                         }
12159                                 }
12160                         offset++;
12161                 }
12162         }
12163
12164         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12165         /* now some housekeeping stuff */
12166         if (aop) {
12167           /* we had to allocate for this iCode */
12168           pic16_freeAsmop(NULL,aop,ic,TRUE);
12169         } else { 
12170           /* we did not allocate which means left
12171            * already in a pointer register, then
12172            * if size > 0 && this could be used again
12173            * we have to point it back to where it 
12174            * belongs */
12175           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12176           if (AOP_SIZE(right) > 1
12177             && !OP_SYMBOL(result)->remat
12178             && ( OP_SYMBOL(result)->liveTo > ic->seq
12179             || ic->depth )) {
12180
12181               int size = AOP_SIZE(right) - 1;
12182
12183                 while (size--)
12184                   pic16_emitcode("decf","fsr0,f");
12185                   //pic16_emitcode("dec","%s",rname);
12186             }
12187         }
12188
12189     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12190     /* done */
12191 //release:
12192     pic16_freeAsmop(right,NULL,ic,TRUE);
12193     pic16_freeAsmop(result,NULL,ic,TRUE);
12194 }
12195
12196 /*-----------------------------------------------------------------*/
12197 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12198 /*-----------------------------------------------------------------*/
12199 static void genPagedPointerSet (operand *right,
12200                                operand *result, 
12201                                iCode *ic)
12202 {
12203     asmop *aop = NULL;
12204     regs *preg = NULL ;
12205     char *rname , *l;
12206     sym_link *retype;
12207        
12208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12209
12210     retype= getSpec(operandType(right));
12211     
12212     pic16_aopOp(result,ic,FALSE);
12213     
12214     /* if the value is already in a pointer register
12215        then don't need anything more */
12216     if (!AOP_INPREG(AOP(result))) {
12217         /* otherwise get a free pointer register */
12218         aop = newAsmop(0);
12219         preg = getFreePtr(ic,&aop,FALSE);
12220         pic16_emitcode("mov","%s,%s",
12221                 preg->name,
12222                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12223         rname = preg->name ;
12224     } else
12225         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12226     
12227     pic16_freeAsmop(result,NULL,ic,TRUE);
12228     pic16_aopOp (right,ic,FALSE);
12229
12230     /* if bitfield then unpack the bits */
12231     if (IS_BITFIELD(retype)) 
12232         genPackBits (retype,result,right,rname,PPOINTER);
12233     else {
12234         /* we have can just get the values */
12235         int size = AOP_SIZE(right);
12236         int offset = 0 ;        
12237         
12238         while (size--) {
12239             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12240             
12241             MOVA(l);
12242             pic16_emitcode("movx","@%s,a",rname);
12243
12244             if (size)
12245                 pic16_emitcode("inc","%s",rname);
12246
12247             offset++;
12248         }
12249     }
12250     
12251     /* now some housekeeping stuff */
12252     if (aop) {
12253         /* we had to allocate for this iCode */
12254         pic16_freeAsmop(NULL,aop,ic,TRUE);
12255     } else { 
12256         /* we did not allocate which means left
12257            already in a pointer register, then
12258            if size > 0 && this could be used again
12259            we have to point it back to where it 
12260            belongs */
12261         if (AOP_SIZE(right) > 1 &&
12262             !OP_SYMBOL(result)->remat &&
12263             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12264               ic->depth )) {
12265             int size = AOP_SIZE(right) - 1;
12266             while (size--)
12267                 pic16_emitcode("dec","%s",rname);
12268         }
12269     }
12270
12271     /* done */
12272     pic16_freeAsmop(right,NULL,ic,TRUE);
12273     
12274         
12275 }
12276
12277 /*-----------------------------------------------------------------*/
12278 /* genFarPointerSet - set value from far space                     */
12279 /*-----------------------------------------------------------------*/
12280 static void genFarPointerSet (operand *right,
12281                               operand *result, iCode *ic)
12282 {
12283     int size, offset ;
12284     sym_link *retype = getSpec(operandType(right));
12285
12286     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12287     pic16_aopOp(result,ic,FALSE);
12288
12289     /* if the operand is already in dptr 
12290     then we do nothing else we move the value to dptr */
12291     if (AOP_TYPE(result) != AOP_STR) {
12292         /* if this is remateriazable */
12293         if (AOP_TYPE(result) == AOP_IMMD)
12294             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12295         else { /* we need to get it byte by byte */
12296             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12297             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12298             if (options.model == MODEL_FLAT24)
12299             {
12300                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12301             }
12302         }
12303     }
12304     /* so dptr know contains the address */
12305     pic16_freeAsmop(result,NULL,ic,TRUE);
12306     pic16_aopOp(right,ic,FALSE);
12307
12308     /* if bit then unpack */
12309     if (IS_BITFIELD(retype)) 
12310         genPackBits(retype,result,right,"dptr",FPOINTER);
12311     else {
12312         size = AOP_SIZE(right);
12313         offset = 0 ;
12314
12315         while (size--) {
12316             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12317             MOVA(l);
12318             pic16_emitcode("movx","@dptr,a");
12319             if (size)
12320                 pic16_emitcode("inc","dptr");
12321         }
12322     }
12323
12324     pic16_freeAsmop(right,NULL,ic,TRUE);
12325 }
12326
12327 /*-----------------------------------------------------------------*/
12328 /* genGenPointerSet - set value from generic pointer space         */
12329 /*-----------------------------------------------------------------*/
12330 #if 0
12331 static void genGenPointerSet (operand *right,
12332                               operand *result, iCode *ic)
12333 {
12334         int i, size, offset, lit;
12335         sym_link *retype = getSpec(operandType(right));
12336
12337         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12338
12339         pic16_aopOp(result,ic,FALSE);
12340         pic16_aopOp(right,ic,FALSE);
12341         size = AOP_SIZE(right);
12342         offset = 0;
12343
12344         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12345
12346         /* if the operand is already in dptr 
12347                 then we do nothing else we move the value to dptr */
12348         if (AOP_TYPE(result) != AOP_STR) {
12349                 /* if this is remateriazable */
12350                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12351                 // WARNING: anythig until "else" is untested!
12352                 if (AOP_TYPE(result) == AOP_IMMD) {
12353                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12354                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12355                         // load FSR0 from immediate
12356                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12357                         offset = 0;
12358                         while(size--) {
12359                                 if(size) {
12360                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12361                                 } else {
12362                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12363                                 }
12364                                 offset++;
12365                         }
12366                         goto release;
12367                 }
12368                 else { /* we need to get it byte by byte */
12369                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12370                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12371
12372                         // set up FSR0 with address of result
12373                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12374                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12375
12376                         /* hack hack! see if this the FSR. If so don't load W */
12377                         if(AOP_TYPE(right) != AOP_ACC) {
12378
12379                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12380
12381                                 if(AOP_TYPE(right) == AOP_LIT)
12382                                 {
12383                                         // copy literal
12384                                         // note: pic16_popGet handles sign extension
12385                                         for(i=0;i<size;i++) {
12386                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12387                                                 if(i < size-1)
12388                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12389                                                 else
12390                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12391                                         }
12392                                 } else {
12393                                         // copy regs
12394
12395                                         for(i=0;i<size;i++) {
12396                                                 if(i < size-1)
12397                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12398                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12399                                                 else
12400                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12401                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12402                                         }
12403                                 }
12404                                 goto release;
12405                         } 
12406                         // right = ACC
12407                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12408                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12409                         goto release;
12410         } // if (AOP_TYPE(result) != AOP_IMMD)
12411
12412         } // if (AOP_TYPE(result) != AOP_STR)
12413         /* so dptr know contains the address */
12414
12415
12416         /* if bit then unpack */
12417         if (IS_BITFIELD(retype)) 
12418                 genPackBits(retype,result,right,"dptr",GPOINTER);
12419         else {
12420                 size = AOP_SIZE(right);
12421                 offset = 0 ;
12422
12423                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12424
12425                 // set up FSR0 with address of result
12426                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12427                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12428         
12429                 while (size--) {
12430                         if (AOP_TYPE(right) == AOP_LIT) {
12431                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12432                                 if (size) {
12433                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12434                                 } else {
12435                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12436                                 }
12437                         } else { // no literal
12438                                 if(size) {
12439                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12440                                 } else {
12441                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12442                                 }
12443                         }
12444                         offset++;
12445                 }
12446         }
12447
12448         release:
12449         pic16_freeAsmop(right,NULL,ic,TRUE);
12450         pic16_freeAsmop(result,NULL,ic,TRUE);
12451 }
12452 #endif
12453
12454 static void genGenPointerSet (operand *right,
12455                               operand *result, iCode *ic)
12456 {
12457   int size;
12458   sym_link *retype = getSpec(operandType(right));
12459   char fgptrput[32];
12460
12461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12462
12463     pic16_aopOp(result,ic,FALSE);
12464     pic16_aopOp(right,ic,FALSE);
12465     size = AOP_SIZE(right);
12466
12467     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12468
12469
12470     /* if bit then unpack */
12471     if (IS_BITFIELD(retype)) {
12472 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12473       genPackBits(retype,result,right,"dptr",GPOINTER);
12474       goto release;
12475     }
12476
12477     size = AOP_SIZE(right);
12478
12479     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12480
12481
12482
12483     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12484
12485     /* value of right+0 is placed on stack, which will be retrieved
12486      * by the support function this restoring the stack. The important
12487      * thing is that there is no need to manually restore stack pointer
12488      * here */
12489     pushaop(AOP(right), 0);
12490 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12491     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12492     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12493     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12494     
12495     /* load address to write to in WREG:FSR0H:FSR0L */
12496     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12497                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12498     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12499                                 pic16_popCopyReg(&pic16_pc_prodl)));
12500     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12501     
12502
12503     /* put code here */
12504     switch (size) {
12505       case 1: strcpy(fgptrput, "__gptrput1"); break;
12506       case 2: strcpy(fgptrput, "__gptrput2"); break;
12507       case 3: strcpy(fgptrput, "__gptrput3"); break;
12508       case 4: strcpy(fgptrput, "__gptrput4"); break;
12509       default:
12510         werror(W_POSSBUG2, __FILE__, __LINE__);
12511         abort();
12512     }
12513     
12514     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12515     
12516     {
12517       symbol *sym;
12518                   
12519         sym = newSymbol( fgptrput, 0 );
12520         sym->used++;
12521         strcpy(sym->rname, fgptrput);
12522         checkAddSym(&externs, sym);
12523     }
12524
12525 release:
12526     pic16_freeAsmop(right,NULL,ic,TRUE);
12527     pic16_freeAsmop(result,NULL,ic,TRUE);
12528 }
12529
12530 /*-----------------------------------------------------------------*/
12531 /* genPointerSet - stores the value into a pointer location        */
12532 /*-----------------------------------------------------------------*/
12533 static void genPointerSet (iCode *ic)
12534 {    
12535   operand *right, *result ;
12536   sym_link *type, *etype;
12537   int p_type;
12538
12539     FENTRY;
12540
12541     right = IC_RIGHT(ic);
12542     result = IC_RESULT(ic) ;
12543
12544     /* depending on the type of pointer we need to
12545     move it to the correct pointer register */
12546     type = operandType(result);
12547     etype = getSpec(type);
12548     /* if left is of type of pointer then it is simple */
12549     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12550         p_type = DCL_TYPE(type);
12551     }
12552     else {
12553         /* we have to go by the storage class */
12554         p_type = PTR_TYPE(SPEC_OCLS(etype));
12555
12556 /*      if (SPEC_OCLS(etype)->codesp ) { */
12557 /*          p_type = CPOINTER ;  */
12558 /*      } */
12559 /*      else */
12560 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12561 /*              p_type = FPOINTER ; */
12562 /*          else */
12563 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12564 /*                  p_type = PPOINTER ; */
12565 /*              else */
12566 /*                  if (SPEC_OCLS(etype) == idata ) */
12567 /*                      p_type = IPOINTER ; */
12568 /*                  else */
12569 /*                      p_type = POINTER ; */
12570     }
12571
12572     /* now that we have the pointer type we assign
12573     the pointer values */
12574     switch (p_type) {
12575       case POINTER:
12576       case IPOINTER:
12577         genNearPointerSet (right,result,ic);
12578         break;
12579
12580       case PPOINTER:
12581         genPagedPointerSet (right,result,ic);
12582         break;
12583
12584       case FPOINTER:
12585         genFarPointerSet (right,result,ic);
12586         break;
12587         
12588       case GPOINTER:
12589         genGenPointerSet (right,result,ic);
12590         break;
12591
12592       default:
12593         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12594           "genPointerSet: illegal pointer type");
12595     }
12596 }
12597
12598 /*-----------------------------------------------------------------*/
12599 /* genIfx - generate code for Ifx statement                        */
12600 /*-----------------------------------------------------------------*/
12601 static void genIfx (iCode *ic, iCode *popIc)
12602 {
12603   operand *cond = IC_COND(ic);
12604   int isbit =0;
12605
12606     FENTRY;
12607
12608     pic16_aopOp(cond,ic,FALSE);
12609
12610     /* get the value into acc */
12611     if (AOP_TYPE(cond) != AOP_CRY)
12612       pic16_toBoolean(cond);
12613     else
12614       isbit = 1;
12615     /* the result is now in the accumulator */
12616     pic16_freeAsmop(cond,NULL,ic,TRUE);
12617
12618     /* if there was something to be popped then do it */
12619     if (popIc)
12620       genIpop(popIc);
12621
12622     /* if the condition is  a bit variable */
12623     if (isbit && IS_ITEMP(cond) && 
12624         SPIL_LOC(cond)) {
12625       genIfxJump(ic,"c");
12626       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12627     } else {
12628       if (isbit && !IS_ITEMP(cond))
12629         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12630         else
12631         genIfxJump(ic,"a");
12632     }
12633     ic->generated = 1;
12634 }
12635
12636 /*-----------------------------------------------------------------*/
12637 /* genAddrOf - generates code for address of                       */
12638 /*-----------------------------------------------------------------*/
12639 static void genAddrOf (iCode *ic)
12640 {
12641   operand *result, *left;
12642   int size;
12643   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12644   pCodeOp *pcop0, *pcop1, *pcop2;
12645
12646     FENTRY;
12647
12648     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12649
12650     sym = OP_SYMBOL( IC_LEFT(ic) );
12651     
12652     if(sym->onStack) {
12653       /* get address of symbol on stack */
12654       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12655 #if 0
12656       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12657                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12658 #endif
12659
12660       // operands on stack are accessible via "FSR2 + index" with index
12661       // starting at 2 for arguments and growing from 0 downwards for
12662       // local variables (index == 0 is not assigned so we add one here)
12663       {
12664         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12665         if (soffs <= 0) {
12666           assert (soffs < 0);
12667           soffs++;
12668         } // if
12669         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12670         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12671         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12672         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12673         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12674         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12675         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12676       }
12677
12678       goto release;
12679     }
12680         
12681 //      if(pic16_debug_verbose) {
12682 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12683 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12684 //      }
12685         
12686     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12687     size = AOP_SIZE(IC_RESULT(ic));
12688
12689     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12690     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12691     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12692         
12693     if (size == 3) {
12694       pic16_emitpcode(POC_MOVLW, pcop0);
12695       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12696       pic16_emitpcode(POC_MOVLW, pcop1);
12697       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12698       pic16_emitpcode(POC_MOVLW, pcop2);
12699       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12700     } else
12701     if (size == 2) {
12702       pic16_emitpcode(POC_MOVLW, pcop0);
12703       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12704       pic16_emitpcode(POC_MOVLW, pcop1);
12705     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12706     } else {
12707       pic16_emitpcode(POC_MOVLW, pcop0);
12708       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12709     }
12710
12711     pic16_freeAsmop(left, NULL, ic, FALSE);
12712 release:
12713     pic16_freeAsmop(result,NULL,ic,TRUE);
12714 }
12715
12716
12717 #if 0
12718 /*-----------------------------------------------------------------*/
12719 /* genFarFarAssign - assignment when both are in far space         */
12720 /*-----------------------------------------------------------------*/
12721 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12722 {
12723     int size = AOP_SIZE(right);
12724     int offset = 0;
12725     char *l ;
12726     /* first push the right side on to the stack */
12727     while (size--) {
12728         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12729         MOVA(l);
12730         pic16_emitcode ("push","acc");
12731     }
12732     
12733     pic16_freeAsmop(right,NULL,ic,FALSE);
12734     /* now assign DPTR to result */
12735     pic16_aopOp(result,ic,FALSE);
12736     size = AOP_SIZE(result);
12737     while (size--) {
12738         pic16_emitcode ("pop","acc");
12739         pic16_aopPut(AOP(result),"a",--offset);
12740     }
12741     pic16_freeAsmop(result,NULL,ic,FALSE);
12742         
12743 }
12744 #endif
12745
12746 /*-----------------------------------------------------------------*/
12747 /* genAssign - generate code for assignment                        */
12748 /*-----------------------------------------------------------------*/
12749 static void genAssign (iCode *ic)
12750 {
12751   operand *result, *right;
12752   int size, offset,know_W;
12753   unsigned long lit = 0L;
12754
12755   result = IC_RESULT(ic);
12756   right  = IC_RIGHT(ic) ;
12757
12758   FENTRY;
12759   
12760   /* if they are the same */
12761   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12762     return ;
12763
12764   /* reversed order operands are aopOp'ed so that result operand
12765    * is effective in case right is a stack symbol. This maneauver
12766    * allows to use the _G.resDirect flag later */
12767   pic16_aopOp(result,ic,TRUE);
12768   pic16_aopOp(right,ic,FALSE);
12769
12770   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12771
12772   /* if they are the same registers */
12773   if (pic16_sameRegs(AOP(right),AOP(result)))
12774     goto release;
12775
12776   /* if the result is a bit */
12777   if (AOP_TYPE(result) == AOP_CRY) {
12778     /* if the right size is a literal then
12779        we know what the value is */
12780     if (AOP_TYPE(right) == AOP_LIT) {
12781           
12782       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12783                   pic16_popGet(AOP(result),0));
12784
12785       if (((int) operandLitValue(right))) 
12786         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12787                        AOP(result)->aopu.aop_dir,
12788                        AOP(result)->aopu.aop_dir);
12789       else
12790         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12791                        AOP(result)->aopu.aop_dir,
12792                        AOP(result)->aopu.aop_dir);
12793       goto release;
12794     }
12795
12796     /* the right is also a bit variable */
12797     if (AOP_TYPE(right) == AOP_CRY) {
12798       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12799       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12800       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12801
12802       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12803                      AOP(result)->aopu.aop_dir,
12804                      AOP(result)->aopu.aop_dir);
12805       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12806                      AOP(right)->aopu.aop_dir,
12807                      AOP(right)->aopu.aop_dir);
12808       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12809                      AOP(result)->aopu.aop_dir,
12810                      AOP(result)->aopu.aop_dir);
12811       goto release ;
12812     }
12813
12814     /* we need to or */
12815     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12816     pic16_toBoolean(right);
12817     emitSKPZ;
12818     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12819     //pic16_aopPut(AOP(result),"a",0);
12820     goto release ;
12821   }
12822
12823   /* bit variables done */
12824   /* general case */
12825   size = AOP_SIZE(result);
12826   offset = 0 ;
12827
12828   if(AOP_TYPE(right) == AOP_LIT) {
12829         if(!IS_FLOAT(operandType( right )))
12830                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12831         else {
12832            union {
12833               unsigned long lit_int;
12834               float lit_float;
12835             } info;
12836         
12837                 /* take care if literal is a float */
12838                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12839                 lit = info.lit_int;
12840         }
12841   }
12842
12843 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12844 //                      sizeof(unsigned long int), sizeof(float));
12845
12846
12847   if (AOP_TYPE(right) == AOP_REG) {
12848     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12849     while (size--) {
12850       
12851       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12852     } // while
12853     goto release;
12854   }
12855
12856   if(AOP_TYPE(right) != AOP_LIT
12857         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12858         && !IS_FUNC(OP_SYM_TYPE(right))
12859         ) {
12860         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12861         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12862
12863         // set up table pointer
12864         if(is_LitOp(right)) {
12865 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12866                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12867                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12868                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12869                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12870                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12871                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12872         } else {
12873 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12874                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12875                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12876                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12877                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12878                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12879                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12880         }
12881
12882         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12883         while(size--) {
12884                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12885                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12886                         pic16_popGet(AOP(result),offset)));
12887                 offset++;
12888         }
12889
12890         size = getSize(OP_SYM_ETYPE(right));
12891         if(AOP_SIZE(result) > size) {
12892                 size = AOP_SIZE(result) - size;
12893                 while(size--) {
12894                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12895                         offset++;
12896                 }
12897         }
12898         goto release;
12899   }
12900
12901
12902
12903 #if 0
12904 /* VR - What is this?! */
12905   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12906     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12907     if(aopIdx(AOP(result),0) == 4) {
12908
12909       /* this is a workaround to save value of right into wreg too,
12910        * value of wreg is going to be used later */
12911       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12912       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12913       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12914       goto release;
12915     } else
12916 //      assert(0);
12917       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12918   }
12919 #endif
12920
12921   know_W=-1;
12922   while (size--) {
12923   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12924     if(AOP_TYPE(right) == AOP_LIT) {
12925       if(lit&0xff) {
12926         if(know_W != (lit&0xff))
12927           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12928         know_W = lit&0xff;
12929         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12930       } else
12931         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12932
12933       lit >>= 8;
12934
12935     } else if (AOP_TYPE(right) == AOP_CRY) {
12936       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12937       if(offset == 0) {
12938         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12939         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12940         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12941       }
12942     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12943         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12944         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12945     } else {
12946       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12947
12948       if(!_G.resDirect)         /* use this aopForSym feature */
12949         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12950     }
12951             
12952     offset++;
12953   }
12954   
12955  release:
12956   pic16_freeAsmop (right,NULL,ic,FALSE);
12957   pic16_freeAsmop (result,NULL,ic,TRUE);
12958 }   
12959
12960 /*-----------------------------------------------------------------*/
12961 /* genJumpTab - generates code for jump table                       */
12962 /*-----------------------------------------------------------------*/
12963 static void genJumpTab (iCode *ic)
12964 {
12965   symbol *jtab;
12966   char *l;
12967   pCodeOp *jt_offs;
12968   pCodeOp *jt_offs_hi;
12969   pCodeOp *jt_label;
12970
12971     FENTRY;
12972
12973     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12974     /* get the condition into accumulator */
12975     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12976     MOVA(l);
12977     /* multiply by three */
12978     pic16_emitcode("add","a,acc");
12979     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12980
12981     jtab = newiTempLabel(NULL);
12982     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12983     pic16_emitcode("jmp","@a+dptr");
12984     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12985
12986 #if 0
12987     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12988     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12989     emitSKPNC;
12990     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12991     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12992     pic16_emitpLabel(jtab->key);
12993
12994 #else
12995
12996     jt_offs = pic16_popGetTempReg(0);
12997     jt_offs_hi = pic16_popGetTempReg(1);
12998     jt_label = pic16_popGetLabel (jtab->key);
12999     //fprintf (stderr, "Creating jump table...\n");
13000
13001     // calculate offset into jump table (idx * sizeof (GOTO))
13002     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
13003     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13004     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13005     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13006     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13007     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13008     pic16_emitpcode(POC_MOVWF , jt_offs);
13009
13010     // prepare PCLATx (set to first entry in jump table)
13011     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13012     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13013     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13014     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13015     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13016
13017     // set PCLATx to selected entry (new PCL is stored in jt_offs)
13018     pic16_emitpcode(POC_ADDWF , jt_offs);
13019     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13020     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13021     emitSKPNC;
13022     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
13023
13024     // release temporaries and prepare jump into table (new PCL --> WREG)
13025     pic16_emitpcode(POC_MOVFW , jt_offs);
13026     pic16_popReleaseTempReg (jt_offs_hi, 1);
13027     pic16_popReleaseTempReg (jt_offs, 0);
13028
13029     // jump into the table
13030     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13031
13032     pic16_emitpLabelFORCE(jtab->key);
13033
13034 #endif
13035     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13036
13037     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13038     /* now generate the jump labels */
13039     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13040          jtab = setNextItem(IC_JTLABELS(ic))) {
13041 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13042         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13043         
13044     }
13045     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13046
13047 }
13048
13049 /*-----------------------------------------------------------------*/
13050 /* genMixedOperation - gen code for operators between mixed types  */
13051 /*-----------------------------------------------------------------*/
13052 /*
13053   TSD - Written for the PIC port - but this unfortunately is buggy.
13054   This routine is good in that it is able to efficiently promote 
13055   types to different (larger) sizes. Unfortunately, the temporary
13056   variables that are optimized out by this routine are sometimes
13057   used in other places. So until I know how to really parse the 
13058   iCode tree, I'm going to not be using this routine :(.
13059 */
13060 static int genMixedOperation (iCode *ic)
13061 {
13062 #if 0
13063   operand *result = IC_RESULT(ic);
13064   sym_link *ctype = operandType(IC_LEFT(ic));
13065   operand *right = IC_RIGHT(ic);
13066   int ret = 0;
13067   int big,small;
13068   int offset;
13069
13070   iCode *nextic;
13071   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13072
13073   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13074
13075   nextic = ic->next;
13076   if(!nextic)
13077     return 0;
13078
13079   nextright = IC_RIGHT(nextic);
13080   nextleft  = IC_LEFT(nextic);
13081   nextresult = IC_RESULT(nextic);
13082
13083   pic16_aopOp(right,ic,FALSE);
13084   pic16_aopOp(result,ic,FALSE);
13085   pic16_aopOp(nextright,  nextic, FALSE);
13086   pic16_aopOp(nextleft,   nextic, FALSE);
13087   pic16_aopOp(nextresult, nextic, FALSE);
13088
13089   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13090
13091     operand *t = right;
13092     right = nextright;
13093     nextright = t; 
13094
13095     pic16_emitcode(";remove right +","");
13096
13097   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13098 /*
13099     operand *t = right;
13100     right = nextleft;
13101     nextleft = t; 
13102 */
13103     pic16_emitcode(";remove left +","");
13104   } else
13105     return 0;
13106
13107   big = AOP_SIZE(nextleft);
13108   small = AOP_SIZE(nextright);
13109
13110   switch(nextic->op) {
13111
13112   case '+':
13113     pic16_emitcode(";optimize a +","");
13114     /* if unsigned or not an integral type */
13115     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13116       pic16_emitcode(";add a bit to something","");
13117     } else {
13118
13119       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13120
13121       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13122         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13123         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13124       } else
13125         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13126
13127       offset = 0;
13128       while(--big) {
13129
13130         offset++;
13131
13132         if(--small) {
13133           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13134             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13135             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13136           }
13137
13138           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13139           emitSKPNC;
13140           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13141                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13142                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13143           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13144           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13145
13146         } else {
13147           pic16_emitcode("rlf","known_zero,w");
13148
13149           /*
13150             if right is signed
13151               btfsc  right,7
13152                addlw ff
13153           */
13154           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13155             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13156             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13157           } else {
13158             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13159           }
13160         }
13161       }
13162       ret = 1;
13163     }
13164   }
13165   ret = 1;
13166
13167 release:
13168   pic16_freeAsmop(right,NULL,ic,TRUE);
13169   pic16_freeAsmop(result,NULL,ic,TRUE);
13170   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13171   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13172   if(ret)
13173     nextic->generated = 1;
13174
13175   return ret;
13176 #else
13177   return 0;
13178 #endif
13179 }
13180 /*-----------------------------------------------------------------*/
13181 /* genCast - gen code for casting                                  */
13182 /*-----------------------------------------------------------------*/
13183 static void genCast (iCode *ic)
13184 {
13185   operand *result = IC_RESULT(ic);
13186   sym_link *ctype = operandType(IC_LEFT(ic));
13187   sym_link *rtype = operandType(IC_RIGHT(ic));
13188   sym_link *restype = operandType(IC_RESULT(ic));
13189   operand *right = IC_RIGHT(ic);
13190   int size, offset ;
13191
13192
13193     FENTRY;
13194
13195         /* if they are equivalent then do nothing */
13196 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13197 //              return ;
13198
13199         pic16_aopOp(right,ic,FALSE) ;
13200         pic16_aopOp(result,ic,FALSE);
13201
13202         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13203
13204
13205         /* if the result is a bit */
13206         if (AOP_TYPE(result) == AOP_CRY) {
13207         
13208                 /* if the right size is a literal then
13209                  * we know what the value is */
13210                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13211
13212                 if (AOP_TYPE(right) == AOP_LIT) {
13213                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13214                                 pic16_popGet(AOP(result),0));
13215
13216                         if (((int) operandLitValue(right))) 
13217                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13218                                         AOP(result)->aopu.aop_dir,
13219                                         AOP(result)->aopu.aop_dir);
13220                         else
13221                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13222                                         AOP(result)->aopu.aop_dir,
13223                                         AOP(result)->aopu.aop_dir);
13224                         goto release;
13225                 }
13226
13227                 /* the right is also a bit variable */
13228                 if (AOP_TYPE(right) == AOP_CRY) {
13229                         emitCLRC;
13230                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13231
13232                         pic16_emitcode("clrc","");
13233                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13234                                 AOP(right)->aopu.aop_dir,
13235                                 AOP(right)->aopu.aop_dir);
13236                         pic16_aopPut(AOP(result),"c",0);
13237                         goto release ;
13238                 }
13239
13240                 /* we need to or */
13241                 if (AOP_TYPE(right) == AOP_REG) {
13242                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13243                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13244                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13245                 }
13246                 pic16_toBoolean(right);
13247                 pic16_aopPut(AOP(result),"a",0);
13248                 goto release ;
13249         }
13250
13251         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13252           int offset = 1;
13253
13254                 size = AOP_SIZE(result);
13255
13256                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13257
13258                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13259                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13260                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13261
13262                 while (size--)
13263                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13264
13265                 goto release;
13266         }
13267
13268         if(IS_BITFIELD(getSpec(restype))
13269           && IS_BITFIELD(getSpec(rtype))) {
13270           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13271         }
13272
13273         /* if they are the same size : or less */
13274         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13275
13276                 /* if they are in the same place */
13277                 if (pic16_sameRegs(AOP(right),AOP(result)))
13278                         goto release;
13279
13280                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13281 #if 0
13282                 if (IS_PTR_CONST(rtype))
13283 #else
13284                 if (IS_CODEPTR(rtype))
13285 #endif
13286                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13287
13288 #if 0
13289                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13290 #else
13291                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13292 #endif
13293                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13294
13295 #if 0
13296                 if(AOP_TYPE(right) == AOP_IMMD) {
13297                   pCodeOp *pcop0, *pcop1, *pcop2;
13298                   symbol *sym = OP_SYMBOL( right );
13299
13300                         size = AOP_SIZE(result);
13301                         /* low */
13302                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13303                         /* high */
13304                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13305                         /* upper */
13306                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13307         
13308                         if (size == 3) {
13309                                 pic16_emitpcode(POC_MOVLW, pcop0);
13310                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13311                                 pic16_emitpcode(POC_MOVLW, pcop1);
13312                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13313                                 pic16_emitpcode(POC_MOVLW, pcop2);
13314                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13315                         } else
13316                         if (size == 2) {
13317                                 pic16_emitpcode(POC_MOVLW, pcop0);
13318                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13319                                 pic16_emitpcode(POC_MOVLW, pcop1);
13320                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13321                         } else {
13322                                 pic16_emitpcode(POC_MOVLW, pcop0);
13323                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13324                         }
13325                 } else
13326 #endif
13327                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13328                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13329                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13330                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13331                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13332                         if(AOP_SIZE(result) <2)
13333                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13334                 } else {
13335                         /* if they in different places then copy */
13336                         size = AOP_SIZE(result);
13337                         offset = 0 ;
13338                         while (size--) {
13339                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13340                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13341                                 offset++;
13342                         }
13343                 }
13344                 goto release;
13345         }
13346
13347         /* if the result is of type pointer */
13348         if (IS_PTR(ctype)) {
13349           int p_type;
13350           sym_link *type = operandType(right);
13351           sym_link *etype = getSpec(type);
13352
13353                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13354
13355                 /* pointer to generic pointer */
13356                 if (IS_GENPTR(ctype)) {
13357                   char *l = zero;
13358             
13359                         if (IS_PTR(type)) 
13360                                 p_type = DCL_TYPE(type);
13361                         else {
13362                 /* we have to go by the storage class */
13363                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13364
13365 /*              if (SPEC_OCLS(etype)->codesp )  */
13366 /*                  p_type = CPOINTER ;  */
13367 /*              else */
13368 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13369 /*                      p_type = FPOINTER ; */
13370 /*                  else */
13371 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13372 /*                          p_type = PPOINTER; */
13373 /*                      else */
13374 /*                          if (SPEC_OCLS(etype) == idata ) */
13375 /*                              p_type = IPOINTER ; */
13376 /*                          else */
13377 /*                              p_type = POINTER ; */
13378             }
13379                 
13380             /* the first two bytes are known */
13381       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13382             size = GPTRSIZE - 1; 
13383             offset = 0 ;
13384             while (size--) {
13385               if(offset < AOP_SIZE(right)) {
13386                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13387                 mov2f(AOP(result), AOP(right), offset);
13388 /*
13389                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13390                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13391                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13392                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13393                 } else { 
13394                   
13395                   pic16_aopPut(AOP(result),
13396                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13397                          offset);
13398                 }
13399 */
13400               } else 
13401                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13402               offset++;
13403             }
13404             /* the last byte depending on type */
13405             switch (p_type) {
13406             case IPOINTER:
13407             case POINTER:
13408                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13409                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13410 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13411                 break;
13412
13413             case CPOINTER:
13414                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13415                 break;
13416
13417             case FPOINTER:
13418               pic16_emitcode(";BUG!? ","%d",__LINE__);
13419                 l = one;
13420                 break;
13421             case PPOINTER:
13422               pic16_emitcode(";BUG!? ","%d",__LINE__);
13423                 l = "#0x03";
13424                 break;
13425
13426             case GPOINTER:
13427                 if (GPTRSIZE > AOP_SIZE(right)) {
13428                   // assume data pointer... THIS MIGHT BE WRONG!
13429                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13430                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13431                 } else {
13432                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13433                 }
13434               break;
13435               
13436             default:
13437                 /* this should never happen */
13438                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13439                        "got unknown pointer type");
13440                 exit(1);
13441             }
13442             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13443             goto release ;
13444         }
13445         
13446         /* just copy the pointers */
13447         size = AOP_SIZE(result);
13448         offset = 0 ;
13449         while (size--) {
13450             pic16_aopPut(AOP(result),
13451                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13452                    offset);
13453             offset++;
13454         }
13455         goto release ;
13456     }
13457     
13458
13459
13460     /* so we now know that the size of destination is greater
13461     than the size of the source.
13462     Now, if the next iCode is an operator then we might be
13463     able to optimize the operation without performing a cast.
13464     */
13465     if(genMixedOperation(ic))
13466       goto release;
13467
13468     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13469     
13470     /* we move to result for the size of source */
13471     size = AOP_SIZE(right);
13472     offset = 0 ;
13473     while (size--) {
13474       mov2f(AOP(result), AOP(right), offset);
13475       offset++;
13476     }
13477
13478     /* now depending on the sign of the destination */
13479     size = AOP_SIZE(result) - AOP_SIZE(right);
13480     /* if unsigned or not an integral type */
13481     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13482       while (size--)
13483         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13484     } else {
13485       /* we need to extend the sign :( */
13486
13487       if(size == 1) {
13488         /* Save one instruction of casting char to int */
13489         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13490         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13491         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13492       } else {
13493         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13494
13495         if(offset)
13496           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13497         else
13498           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13499         
13500         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13501
13502         while (size--)
13503           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13504       }
13505     }
13506
13507 release:
13508     pic16_freeAsmop(right,NULL,ic,TRUE);
13509     pic16_freeAsmop(result,NULL,ic,TRUE);
13510
13511 }
13512
13513 /*-----------------------------------------------------------------*/
13514 /* genDjnz - generate decrement & jump if not zero instrucion      */
13515 /*-----------------------------------------------------------------*/
13516 static int genDjnz (iCode *ic, iCode *ifx)
13517 {
13518     symbol *lbl, *lbl1;
13519     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13520
13521     if (!ifx)
13522         return 0;
13523     
13524     /* if the if condition has a false label
13525        then we cannot save */
13526     if (IC_FALSE(ifx))
13527         return 0;
13528
13529     /* if the minus is not of the form 
13530        a = a - 1 */
13531     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13532         !IS_OP_LITERAL(IC_RIGHT(ic)))
13533         return 0;
13534
13535     if (operandLitValue(IC_RIGHT(ic)) != 1)
13536         return 0;
13537
13538     /* if the size of this greater than one then no
13539        saving */
13540     if (getSize(operandType(IC_RESULT(ic))) > 1)
13541         return 0;
13542
13543     /* otherwise we can save BIG */
13544     lbl = newiTempLabel(NULL);
13545     lbl1= newiTempLabel(NULL);
13546
13547     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13548     
13549     if (IS_AOP_PREG(IC_RESULT(ic))) {
13550         pic16_emitcode("dec","%s",
13551                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13552         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13553         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13554     } else {    
13555
13556
13557       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13558       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13559
13560       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13561       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13562
13563     }
13564     
13565     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13566     ifx->generated = 1;
13567     return 1;
13568 }
13569
13570 /*-----------------------------------------------------------------*/
13571 /* genReceive - generate code for a receive iCode                  */
13572 /*-----------------------------------------------------------------*/
13573 static void genReceive (iCode *ic)
13574 {    
13575
13576   FENTRY;
13577
13578 #if 0
13579   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13580         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13581 #endif
13582 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13583
13584   if (isOperandInFarSpace(IC_RESULT(ic))
13585       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13586           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13587
13588     int size = getSize(operandType(IC_RESULT(ic)));
13589     int offset =  pic16_fReturnSizePic - size;
13590
13591       assert( 0 );
13592       while (size--) {
13593         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13594                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13595                       offset++;
13596         }
13597
13598       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13599
13600       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13601       size = AOP_SIZE(IC_RESULT(ic));
13602       offset = 0;
13603       while (size--) {
13604         pic16_emitcode ("pop","acc");
13605         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13606       }
13607   } else {
13608     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13609     _G.accInUse++;
13610     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13611     _G.accInUse--;
13612
13613     /* set pseudo stack pointer to where it should be - dw*/
13614     GpsuedoStkPtr = ic->parmBytes;
13615
13616     /* setting GpsuedoStkPtr has side effects here: */
13617     assignResultValue(IC_RESULT(ic), 0);
13618   }
13619
13620   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13621 }
13622
13623 /*-----------------------------------------------------------------*/
13624 /* genDummyRead - generate code for dummy read of volatiles        */
13625 /*-----------------------------------------------------------------*/
13626 static void
13627 genDummyRead (iCode * ic)
13628 {
13629   operand *op;
13630   int i;
13631
13632   op = IC_RIGHT(ic);
13633   if (op && IS_SYMOP(op)) {
13634     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13635       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13636       return;
13637     }
13638     pic16_aopOp (op, ic, FALSE);
13639     for (i=0; i < AOP_SIZE(op); i++) {
13640       // may need to protect this from the peepholer -- this is not nice but works...
13641       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13642       pic16_mov2w (AOP(op),i);
13643       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13644     } // for i
13645     pic16_freeAsmop (op, NULL, ic, TRUE);
13646   } else if (op) {
13647     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13648   } // if
13649 }
13650
13651 /*-----------------------------------------------------------------*/
13652 /* genpic16Code - generate code for pic16 based controllers        */
13653 /*-----------------------------------------------------------------*/
13654 /*
13655  * At this point, ralloc.c has gone through the iCode and attempted
13656  * to optimize in a way suitable for a PIC. Now we've got to generate
13657  * PIC instructions that correspond to the iCode.
13658  *
13659  * Once the instructions are generated, we'll pass through both the
13660  * peep hole optimizer and the pCode optimizer.
13661  *-----------------------------------------------------------------*/
13662
13663 void genpic16Code (iCode *lic)
13664 {
13665   iCode *ic;
13666   int cln = 0;
13667
13668     lineHead = lineCurr = NULL;
13669
13670     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13671     pic16_addpBlock(pb);
13672
13673 #if 0
13674     /* if debug information required */
13675     if (options.debug && currFunc) {
13676       if (currFunc) {
13677         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13678       }
13679     }
13680 #endif
13681
13682     for (ic = lic ; ic ; ic = ic->next ) {
13683
13684       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13685       if ( cln != ic->lineno ) {
13686         if ( options.debug ) {
13687           debugFile->writeCLine (ic);
13688         }
13689         
13690         if(!options.noCcodeInAsm) {
13691           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13692               printCLine(ic->filename, ic->lineno)));
13693         }
13694
13695         cln = ic->lineno ;
13696       }
13697         
13698       if(options.iCodeInAsm) {
13699         char *l;
13700
13701           /* insert here code to print iCode as comment */
13702           l = Safe_strdup(printILine(ic));
13703           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13704       }
13705         
13706       /* if the result is marked as
13707        * spilt and rematerializable or code for
13708        * this has already been generated then
13709        * do nothing */
13710       if (resultRemat(ic) || ic->generated ) 
13711         continue ;
13712         
13713       /* depending on the operation */
13714       switch (ic->op) {
13715         case '!' :
13716           pic16_genNot(ic);
13717           break;
13718             
13719         case '~' :
13720           pic16_genCpl(ic);
13721           break;
13722             
13723         case UNARYMINUS:
13724           genUminus (ic);
13725           break;
13726             
13727         case IPUSH:
13728           genIpush (ic);
13729           break;
13730             
13731         case IPOP:
13732           /* IPOP happens only when trying to restore a 
13733            * spilt live range, if there is an ifx statement
13734            * following this pop then the if statement might
13735            * be using some of the registers being popped which
13736            * would destroy the contents of the register so
13737            * we need to check for this condition and handle it */
13738            if (ic->next
13739              && ic->next->op == IFX
13740              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13741                genIfx (ic->next,ic);
13742           else
13743             genIpop (ic);
13744           break; 
13745             
13746         case CALL:
13747           genCall (ic);
13748           break;
13749             
13750         case PCALL:
13751           genPcall (ic);
13752           break;
13753             
13754         case FUNCTION:
13755           genFunction (ic);
13756           break;
13757             
13758         case ENDFUNCTION:
13759           genEndFunction (ic);
13760           break;
13761             
13762         case RETURN:
13763           genRet (ic);
13764           break;
13765             
13766         case LABEL:
13767           genLabel (ic);
13768           break;
13769             
13770         case GOTO:
13771           genGoto (ic);
13772           break;
13773             
13774         case '+' :
13775           pic16_genPlus (ic) ;
13776           break;
13777             
13778         case '-' :
13779           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13780             pic16_genMinus (ic);
13781           break;
13782
13783         case '*' :
13784           genMult (ic);
13785           break;
13786             
13787         case '/' :
13788           genDiv (ic) ;
13789           break;
13790             
13791         case '%' :
13792           genMod (ic);
13793           break;
13794             
13795         case '>' :
13796           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13797           break;
13798             
13799         case '<' :
13800           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13801           break;
13802             
13803         case LE_OP:
13804         case GE_OP:
13805         case NE_OP:
13806           /* note these two are xlated by algebraic equivalence
13807            * during parsing SDCC.y */
13808           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13809             "got '>=' or '<=' shouldn't have come here");
13810           break;
13811
13812         case EQ_OP:
13813           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13814           break;            
13815             
13816         case AND_OP:
13817           genAndOp (ic);
13818           break;
13819             
13820         case OR_OP:
13821           genOrOp (ic);
13822           break;
13823             
13824         case '^' :
13825           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13826           break;
13827             
13828         case '|' :
13829           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13830           break;
13831             
13832         case BITWISEAND:
13833           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13834           break;
13835             
13836         case INLINEASM:
13837           genInline (ic);
13838           break;
13839             
13840         case RRC:
13841           genRRC (ic);
13842           break;
13843             
13844         case RLC:
13845           genRLC (ic);
13846           break;
13847             
13848         case GETHBIT:
13849           genGetHbit (ic);
13850           break;
13851             
13852         case LEFT_OP:
13853           genLeftShift (ic);
13854           break;
13855             
13856         case RIGHT_OP:
13857           genRightShift (ic);
13858           break;
13859             
13860         case GET_VALUE_AT_ADDRESS:
13861           genPointerGet(ic);
13862           break;
13863             
13864         case '=' :
13865           if (POINTER_SET(ic))
13866             genPointerSet(ic);
13867           else
13868             genAssign(ic);
13869           break;
13870             
13871         case IFX:
13872           genIfx (ic,NULL);
13873           break;
13874             
13875         case ADDRESS_OF:
13876           genAddrOf (ic);
13877           break;
13878             
13879         case JUMPTABLE:
13880           genJumpTab (ic);
13881           break;
13882             
13883         case CAST:
13884           genCast (ic);
13885           break;
13886             
13887         case RECEIVE:
13888           genReceive(ic);
13889           break;
13890             
13891         case SEND:
13892           addSet(&_G.sendSet,ic);
13893           break;
13894
13895         case DUMMY_READ_VOLATILE:
13896           genDummyRead (ic);
13897           break;
13898
13899         default :
13900           ic = ic;
13901       }
13902     }
13903
13904
13905     /* now we are ready to call the
13906        peep hole optimizer */
13907     if (!options.nopeep)
13908       peepHole (&lineHead);
13909
13910     /* now do the actual printing */
13911     printLine (lineHead, codeOutFile);
13912
13913 #ifdef PCODE_DEBUG
13914     DFPRINTF((stderr,"printing pBlock\n\n"));
13915     pic16_printpBlock(stdout,pb);
13916 #endif
13917
13918     return;
13919 }
13920