* src/SDCCast.c (processParms): disabled W_NONRENT_ARGS for pic16 port
[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 //      debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", 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\n", __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: assert (offset==0); break;
2057         default:
2058           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2059           assert( 0 );  /* should never reach here */;
2060       }
2061       return pcop;
2062     }
2063
2064     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2065            "pic16_popGet got unsupported aop->type");
2066     exit(0);
2067 }
2068 /*-----------------------------------------------------------------*/
2069 /* pic16_aopPut - puts a string for a aop                                */
2070 /*-----------------------------------------------------------------*/
2071 void pic16_aopPut (asmop *aop, char *s, int offset)
2072 {
2073     char *d = buffer ;
2074     symbol *lbl ;
2075
2076     return;
2077
2078     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2079
2080     if (aop->size && offset > ( aop->size - 1)) {
2081         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2082                "pic16_aopPut got offset > aop->size");
2083         exit(0);
2084     }
2085
2086     /* will assign value to value */
2087     /* depending on where it is ofcourse */
2088     switch (aop->type) {
2089     case AOP_DIR:
2090       if (offset) {
2091         sprintf(d,"(%s + %d)",
2092                 aop->aopu.aop_dir,offset);
2093         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2094
2095       } else
2096             sprintf(d,"%s",aop->aopu.aop_dir);
2097         
2098         if (strcmp(d,s)) {
2099           DEBUGpic16_emitcode(";","%d",__LINE__);
2100           if(strcmp(s,"W"))
2101             pic16_emitcode("movf","%s,w",s);
2102           pic16_emitcode("movwf","%s",d);
2103
2104           if(strcmp(s,"W")) {
2105             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2106             if(offset >= aop->size) {
2107               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2108               break;
2109             } else
2110               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2111           }
2112
2113           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2114
2115
2116         }
2117         break;
2118         
2119     case AOP_REG:
2120       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2121         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2122           /*
2123             if (*s == '@'           ||
2124                 strcmp(s,"r0") == 0 ||
2125                 strcmp(s,"r1") == 0 ||
2126                 strcmp(s,"r2") == 0 ||
2127                 strcmp(s,"r3") == 0 ||
2128                 strcmp(s,"r4") == 0 ||
2129                 strcmp(s,"r5") == 0 ||
2130                 strcmp(s,"r6") == 0 || 
2131                 strcmp(s,"r7") == 0 )
2132                 pic16_emitcode("mov","%s,%s  ; %d",
2133                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2134             else
2135           */
2136
2137           if(strcmp(s,"W")==0 )
2138             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2139
2140           pic16_emitcode("movwf","%s",
2141                    aop->aopu.aop_reg[offset]->name);
2142
2143           if(strcmp(s,zero)==0) {
2144             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2145
2146           } else if(strcmp(s,"W")==0) {
2147             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2148             pcop->type = PO_GPR_REGISTER;
2149
2150             PCOR(pcop)->rIdx = -1;
2151             PCOR(pcop)->r = NULL;
2152
2153             DEBUGpic16_emitcode(";","%d",__LINE__);
2154             pcop->name = Safe_strdup(s);
2155             pic16_emitpcode(POC_MOVFW,pcop);
2156             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2157           } else if(strcmp(s,one)==0) {
2158             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2159             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2160           } else {
2161             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2162           }
2163         }
2164         break;
2165         
2166     case AOP_DPTR:
2167     case AOP_DPTR2:
2168     
2169     if (aop->type == AOP_DPTR2)
2170     {
2171         genSetDPTR(1);
2172     }
2173     
2174         if (aop->code) {
2175             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2176                    "pic16_aopPut writting to code space");
2177             exit(0);
2178         }
2179         
2180         while (offset > aop->coff) {
2181             aop->coff++;
2182             pic16_emitcode ("inc","dptr");
2183         }
2184         
2185         while (offset < aop->coff) {
2186             aop->coff-- ;
2187             pic16_emitcode("lcall","__decdptr");
2188         }
2189         
2190         aop->coff = offset;
2191         
2192         /* if not in accumulater */
2193         MOVA(s);        
2194         
2195         pic16_emitcode ("movx","@dptr,a");
2196         
2197     if (aop->type == AOP_DPTR2)
2198     {
2199         genSetDPTR(0);
2200     }
2201         break;
2202         
2203     case AOP_R0:
2204     case AOP_R1:
2205         while (offset > aop->coff) {
2206             aop->coff++;
2207             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2208         }
2209         while (offset < aop->coff) {
2210             aop->coff-- ;
2211             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2212         }
2213         aop->coff = offset;
2214         
2215         if (aop->paged) {
2216             MOVA(s);           
2217             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2218             
2219         } else
2220             if (*s == '@') {
2221                 MOVA(s);
2222                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2223             } else
2224                 if (strcmp(s,"r0") == 0 ||
2225                     strcmp(s,"r1") == 0 ||
2226                     strcmp(s,"r2") == 0 ||
2227                     strcmp(s,"r3") == 0 ||
2228                     strcmp(s,"r4") == 0 ||
2229                     strcmp(s,"r5") == 0 ||
2230                     strcmp(s,"r6") == 0 || 
2231                     strcmp(s,"r7") == 0 ) {
2232                     char buffer[10];
2233                     sprintf(buffer,"a%s",s);
2234                     pic16_emitcode("mov","@%s,%s",
2235                              aop->aopu.aop_ptr->name,buffer);
2236                 } else
2237                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2238         
2239         break;
2240         
2241     case AOP_STK:
2242         if (strcmp(s,"a") == 0)
2243             pic16_emitcode("push","acc");
2244         else
2245             pic16_emitcode("push","%s",s);
2246         
2247         break;
2248         
2249     case AOP_CRY:
2250         /* if bit variable */
2251         if (!aop->aopu.aop_dir) {
2252             pic16_emitcode("clr","a");
2253             pic16_emitcode("rlc","a");
2254         } else {
2255             if (s == zero) 
2256                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2257             else
2258                 if (s == one)
2259                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2260                 else
2261                     if (!strcmp(s,"c"))
2262                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2263                     else {
2264                         lbl = newiTempLabel(NULL);
2265                         
2266                         if (strcmp(s,"a")) {
2267                             MOVA(s);
2268                         }
2269                         pic16_emitcode("clr","c");
2270                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2271                         pic16_emitcode("cpl","c");
2272                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2273                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2274                     }
2275         }
2276         break;
2277         
2278     case AOP_STR:
2279         aop->coff = offset;
2280         if (strcmp(aop->aopu.aop_str[offset],s))
2281             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2282         break;
2283         
2284     case AOP_ACC:
2285         aop->coff = offset;
2286         if (!offset && (strcmp(s,"acc") == 0))
2287             break;
2288         
2289         if (strcmp(aop->aopu.aop_str[offset],s))
2290             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2291         break;
2292
2293     default :
2294         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2295 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2296 //             "pic16_aopPut got unsupported aop->type");
2297 //      exit(0);    
2298     }    
2299
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2304 /*-----------------------------------------------------------------*/
2305 void pic16_mov2w (asmop *aop, int offset)
2306 {
2307   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2308
2309   if(is_LitAOp(aop))
2310     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2311   else
2312     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2313 }
2314
2315 static void mov2f(asmop *dst, asmop *src, int offset)
2316 {
2317   if(is_LitAOp(src)) {
2318     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2319     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2320   } else {
2321     if(pic16_sameRegsOfs(src, dst, offset))return;
2322     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2323                       pic16_popGet(dst, offset)));
2324   }
2325 }
2326
2327 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2328 {
2329   if(is_LitAOp(src)) {
2330     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2331     pic16_emitpcode(POC_MOVWF, dst);
2332   } else {
2333     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2334   }
2335 }
2336
2337 void pic16_testStackOverflow(void)
2338 {
2339 #define GSTACK_TEST_NAME        "__gstack_test"
2340
2341   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2342   
2343   {
2344     symbol *sym;
2345
2346       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2347       strcpy(sym->rname, GSTACK_TEST_NAME);
2348       checkAddSym(&externs, sym);
2349   }
2350
2351 }
2352
2353 /* push pcop into stack */
2354 void pic16_pushpCodeOp(pCodeOp *pcop)
2355 {
2356 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2357   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2358   if(pic16_options.gstack)
2359     pic16_testStackOverflow();
2360     
2361 }
2362
2363 /* pop pcop from stack */
2364 void pic16_poppCodeOp(pCodeOp *pcop)
2365 {
2366   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2367   if(pic16_options.gstack)
2368     pic16_testStackOverflow();
2369 }
2370
2371
2372 /*-----------------------------------------------------------------*/
2373 /* pushw - pushes wreg to stack                                    */
2374 /*-----------------------------------------------------------------*/
2375 void pushw(void)
2376 {
2377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2378   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2379   if(pic16_options.gstack)
2380     pic16_testStackOverflow();
2381 }
2382
2383                 
2384 /*-----------------------------------------------------------------*/
2385 /* pushaop - pushes aop to stack                                   */
2386 /*-----------------------------------------------------------------*/
2387 void pushaop(asmop *aop, int offset)
2388 {
2389   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2390
2391   if(is_LitAOp(aop)) {
2392     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2393     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2394   } else {
2395     pic16_emitpcode(POC_MOVFF,
2396       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2397   }
2398
2399   if(pic16_options.gstack)
2400     pic16_testStackOverflow();
2401 }
2402
2403 /*-----------------------------------------------------------------*/
2404 /* popaop - pops aop from stack                                    */
2405 /*-----------------------------------------------------------------*/
2406 void popaop(asmop *aop, int offset)
2407 {
2408   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2409   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2410   if(pic16_options.gstack)
2411     pic16_testStackOverflow();
2412 }
2413
2414 void popaopidx(asmop *aop, int offset, int index)
2415 {
2416   int ofs=1;
2417
2418     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2419
2420     if(STACK_MODEL_LARGE)ofs++;
2421
2422     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2423     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2424     if(pic16_options.gstack)
2425       pic16_testStackOverflow();
2426 }
2427
2428 #if !(USE_GENERIC_SIGNED_SHIFT)
2429 /*-----------------------------------------------------------------*/
2430 /* reAdjustPreg - points a register back to where it should        */
2431 /*-----------------------------------------------------------------*/
2432 static void reAdjustPreg (asmop *aop)
2433 {
2434     int size ;
2435
2436     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2437     aop->coff = 0;
2438     if ((size = aop->size) <= 1)
2439         return ;
2440     size-- ;
2441     switch (aop->type) {
2442         case AOP_R0 :
2443         case AOP_R1 :
2444             while (size--)
2445                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2446             break;          
2447         case AOP_DPTR :
2448         case AOP_DPTR2:
2449             if (aop->type == AOP_DPTR2)
2450             {
2451                 genSetDPTR(1);
2452             } 
2453             while (size--)
2454             {
2455                 pic16_emitcode("lcall","__decdptr");
2456             }
2457                 
2458             if (aop->type == AOP_DPTR2)
2459             {
2460                 genSetDPTR(0);
2461             }                
2462             break;  
2463
2464     }   
2465
2466 }
2467 #endif
2468
2469 #if 0
2470 /*-----------------------------------------------------------------*/
2471 /* opIsGptr: returns non-zero if the passed operand is             */   
2472 /* a generic pointer type.                                         */
2473 /*-----------------------------------------------------------------*/ 
2474 static int opIsGptr(operand *op)
2475 {
2476     sym_link *type = operandType(op);
2477     
2478     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2479     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2480     {
2481         return 1;
2482     }
2483     return 0;        
2484 }
2485 #endif
2486
2487 /*-----------------------------------------------------------------*/
2488 /* pic16_getDataSize - get the operand data size                         */
2489 /*-----------------------------------------------------------------*/
2490 int pic16_getDataSize(operand *op)
2491 {
2492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493
2494
2495     return AOP_SIZE(op);
2496
2497     // tsd- in the pic port, the genptr size is 1, so this code here
2498     // fails. ( in the 8051 port, the size was 4).
2499 #if 0
2500     int size;
2501     size = AOP_SIZE(op);
2502     if (size == GPTRSIZE)
2503     {
2504         sym_link *type = operandType(op);
2505         if (IS_GENPTR(type))
2506         {
2507             /* generic pointer; arithmetic operations
2508              * should ignore the high byte (pointer type).
2509              */
2510             size--;
2511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2512         }
2513     }
2514     return size;
2515 #endif
2516 }
2517
2518 /*-----------------------------------------------------------------*/
2519 /* pic16_outAcc - output Acc                                             */
2520 /*-----------------------------------------------------------------*/
2521 void pic16_outAcc(operand *result)
2522 {
2523   int size,offset;
2524   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2525   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2526
2527
2528   size = pic16_getDataSize(result);
2529   if(size){
2530     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2531     size--;
2532     offset = 1;
2533     /* unsigned or positive */
2534     while(size--)
2535       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2536   }
2537
2538 }
2539
2540 /*-----------------------------------------------------------------*/
2541 /* pic16_outBitC - output a bit C                                  */
2542 /*                 Move to result the value of Carry flag -- VR    */
2543 /*-----------------------------------------------------------------*/
2544 void pic16_outBitC(operand *result)
2545 {
2546   int i;
2547
2548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2549
2550     /* if the result is bit */
2551     if (AOP_TYPE(result) == AOP_CRY) {
2552         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2553         pic16_aopPut(AOP(result),"c",0);
2554     } else {
2555
2556         i = AOP_SIZE(result);
2557         while(i--) {
2558                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2559         }
2560         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2561     }
2562 }
2563
2564 /*-----------------------------------------------------------------*/
2565 /* pic16_outBitOp - output a bit from Op                           */
2566 /*                 Move to result the value of set/clr op -- VR    */
2567 /*-----------------------------------------------------------------*/
2568 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2569 {
2570   int i;
2571
2572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2573
2574     /* if the result is bit */
2575     if (AOP_TYPE(result) == AOP_CRY) {
2576         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2577         pic16_aopPut(AOP(result),"c",0);
2578     } else {
2579
2580         i = AOP_SIZE(result);
2581         while(i--) {
2582                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2583         }
2584         pic16_emitpcode(POC_RRCF, pcop);          
2585         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2586     }
2587 }
2588
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2591 /*-----------------------------------------------------------------*/
2592 void pic16_toBoolean(operand *oper)
2593 {
2594     int size = AOP_SIZE(oper) - 1;
2595     int offset = 1;
2596
2597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2598
2599     if ( AOP_TYPE(oper) != AOP_ACC) {
2600       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2601     }
2602     while (size--) {
2603       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2604     }
2605 }
2606
2607
2608 #if !defined(GEN_Not)
2609 /*-----------------------------------------------------------------*/
2610 /* genNot - generate code for ! operation                          */
2611 /*-----------------------------------------------------------------*/
2612 static void pic16_genNot (iCode *ic)
2613 {
2614   symbol *tlbl;
2615   int size;
2616
2617   FENTRY;
2618   /* assign asmOps to operand & result */
2619   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2620   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2621
2622   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2623   /* if in bit space then a special case */
2624   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2625     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2626       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2627       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2628     } else {
2629       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2630       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2631       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2632     }
2633     goto release;
2634   }
2635
2636   size = AOP_SIZE(IC_LEFT(ic));
2637   if(size == 1) {
2638     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2639     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2640     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2641     goto release;
2642   }
2643   pic16_toBoolean(IC_LEFT(ic));
2644
2645   tlbl = newiTempLabel(NULL);
2646   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2647   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2648   pic16_outBitC(IC_RESULT(ic));
2649
2650  release:    
2651   /* release the aops */
2652   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2653   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2654 }
2655 #endif
2656
2657
2658 #if !defined(GEN_Cpl)
2659 /*-----------------------------------------------------------------*/
2660 /* genCpl - generate code for complement                           */
2661 /*-----------------------------------------------------------------*/
2662 static void pic16_genCpl (iCode *ic)
2663 {
2664   int offset = 0;
2665   int size ;
2666
2667     FENTRY;
2668     /* assign asmOps to operand & result */
2669     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2670     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2671
2672     /* if both are in bit space then 
2673     a special case */
2674     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2675         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2676
2677         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2678         pic16_emitcode("cpl","c"); 
2679         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2680         goto release; 
2681     } 
2682
2683     size = AOP_SIZE(IC_RESULT(ic));
2684     while (size--) {
2685 /*
2686         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2687         MOVA(l);       
2688         pic16_emitcode("cpl","a");
2689         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2690 */
2691         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2692               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2693         } else {
2694                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2695                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2696         }
2697         offset++;
2698
2699     }
2700
2701
2702 release:
2703     /* release the aops */
2704     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2705     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2706 }
2707 #endif
2708
2709 /*-----------------------------------------------------------------*/
2710 /* genUminusFloat - unary minus for floating points                */
2711 /*-----------------------------------------------------------------*/
2712 static void genUminusFloat(operand *op,operand *result)
2713 {
2714   int size ,offset =0 ;
2715   
2716     FENTRY;
2717     /* for this we just need to flip the 
2718     first it then copy the rest in place */
2719     size = AOP_SIZE(op);
2720
2721     while(size--) {
2722       mov2f(AOP(result), AOP(op), offset);
2723       offset++;
2724     }
2725     
2726     /* toggle the MSB's highest bit */
2727     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2728 }
2729
2730 /*-----------------------------------------------------------------*/
2731 /* genUminus - unary minus code generation                         */
2732 /*-----------------------------------------------------------------*/
2733 static void genUminus (iCode *ic)
2734 {
2735   int size, i;
2736   sym_link *optype, *rtype;
2737   symbol *label;
2738   int needLabel=0;
2739
2740     FENTRY;     
2741     
2742     /* assign asmops */
2743     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2744     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2745
2746     /* if both in bit space then special case */
2747     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2748       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2749         
2750         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2751         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2752         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2753         goto release; 
2754     } 
2755
2756     optype = operandType(IC_LEFT(ic));
2757     rtype = operandType(IC_RESULT(ic));
2758
2759     /* if float then do float stuff */
2760     if (IS_FLOAT(optype)) {
2761       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2762       goto release;
2763     }
2764
2765     /* otherwise subtract from zero by taking the 2's complement */
2766     size = AOP_SIZE(IC_LEFT(ic));
2767     label = newiTempLabel ( NULL );
2768     
2769     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2770       for (i=size-1; i > 0; i--) {
2771         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2772       } // for
2773       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2774       for (i=1; i < size; i++) {
2775         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2776         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2777       } // for
2778     } else {
2779       for (i=size-1; i >= 0; i--) {
2780         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2781         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2782       } // for
2783       if (size > 1) {
2784         for (i=0; i < size-2; i++) {
2785           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2786           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2787         } // for
2788         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2789       } // if
2790       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2791     }
2792     if (needLabel)
2793       pic16_emitpLabel (label->key);
2794
2795 release:
2796     /* release the aops */
2797     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2798     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2799 }
2800
2801 #if 0
2802 /*-----------------------------------------------------------------*/
2803 /* saveRegisters - will look for a call and save the registers     */
2804 /*-----------------------------------------------------------------*/
2805 static void saveRegisters(iCode *lic) 
2806 {
2807     int i;
2808     iCode *ic;
2809     bitVect *rsave;
2810     sym_link *dtype;
2811
2812     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2813     /* look for call */
2814     for (ic = lic ; ic ; ic = ic->next) 
2815         if (ic->op == CALL || ic->op == PCALL)
2816             break;
2817
2818     if (!ic) {
2819         fprintf(stderr,"found parameter push with no function call\n");
2820         return ;
2821     }
2822
2823     /* if the registers have been saved already then
2824     do nothing */
2825     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2826         return ;
2827
2828     /* find the registers in use at this time 
2829     and push them away to safety */
2830     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2831                           ic->rUsed);
2832
2833     ic->regsSaved = 1;
2834     if (options.useXstack) {
2835         if (bitVectBitValue(rsave,R0_IDX))
2836             pic16_emitcode("mov","b,r0");
2837         pic16_emitcode("mov","r0,%s",spname);
2838         for (i = 0 ; i < pic16_nRegs ; i++) {
2839             if (bitVectBitValue(rsave,i)) {
2840                 if (i == R0_IDX)
2841                     pic16_emitcode("mov","a,b");
2842                 else
2843                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2844                 pic16_emitcode("movx","@r0,a");
2845                 pic16_emitcode("inc","r0");
2846             }
2847         }
2848         pic16_emitcode("mov","%s,r0",spname);
2849         if (bitVectBitValue(rsave,R0_IDX))
2850             pic16_emitcode("mov","r0,b");           
2851     }// else
2852     //for (i = 0 ; i < pic16_nRegs ; i++) {
2853     //    if (bitVectBitValue(rsave,i))
2854     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2855     //}
2856
2857     dtype = operandType(IC_LEFT(ic));
2858     if (currFunc && dtype && 
2859         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2860         IFFUNC_ISISR(currFunc->type) &&
2861         !ic->bankSaved) 
2862
2863         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2864
2865 }
2866 /*-----------------------------------------------------------------*/
2867 /* unsaveRegisters - pop the pushed registers                      */
2868 /*-----------------------------------------------------------------*/
2869 static void unsaveRegisters (iCode *ic)
2870 {
2871     int i;
2872     bitVect *rsave;
2873
2874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2875     /* find the registers in use at this time 
2876     and push them away to safety */
2877     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2878                           ic->rUsed);
2879     
2880     if (options.useXstack) {
2881         pic16_emitcode("mov","r0,%s",spname);   
2882         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2883             if (bitVectBitValue(rsave,i)) {
2884                 pic16_emitcode("dec","r0");
2885                 pic16_emitcode("movx","a,@r0");
2886                 if (i == R0_IDX)
2887                     pic16_emitcode("mov","b,a");
2888                 else
2889                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2890             }       
2891
2892         }
2893         pic16_emitcode("mov","%s,r0",spname);
2894         if (bitVectBitValue(rsave,R0_IDX))
2895             pic16_emitcode("mov","r0,b");
2896     } //else
2897     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2898     //    if (bitVectBitValue(rsave,i))
2899     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2900     //}
2901
2902 }  
2903 #endif
2904
2905 #if 0  // patch 14
2906 /*-----------------------------------------------------------------*/
2907 /* pushSide -                                                      */
2908 /*-----------------------------------------------------------------*/
2909 static void pushSide(operand * oper, int size)
2910 {
2911         int offset = 0;
2912     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2913         while (size--) {
2914                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2915                 if (AOP_TYPE(oper) != AOP_REG &&
2916                     AOP_TYPE(oper) != AOP_DIR &&
2917                     strcmp(l,"a") ) {
2918                         pic16_emitcode("mov","a,%s",l);
2919                         pic16_emitcode("push","acc");
2920                 } else
2921                         pic16_emitcode("push","%s",l);
2922         }
2923 }
2924 #endif // patch 14
2925
2926 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2927 {
2928   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2929     pic16_emitpcode(POC_MOVFW, src);
2930     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2931   } else {
2932     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2933         src, pic16_popGet(AOP(op), offset)));
2934   }
2935 }
2936
2937
2938 /*-----------------------------------------------------------------*/
2939 /* assignResultValue - assign results to oper, rescall==1 is       */
2940 /*                     called from genCall() or genPcall()         */
2941 /*-----------------------------------------------------------------*/
2942 static void assignResultValue(operand * oper, int rescall)
2943 {
2944   int size = AOP_SIZE(oper);
2945   int offset=0;
2946   
2947     FENTRY2;
2948 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2949     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2950
2951     if(rescall) {
2952       /* assign result from a call/pcall function() */
2953                 
2954       /* function results are stored in a special order,
2955        * see top of file with Function return policy, or manual */
2956
2957       if(size <= 4) {
2958         /* 8-bits, result in WREG */
2959         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2960                         
2961         if(size>1) {
2962           /* 16-bits, result in PRODL:WREG */
2963           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2964         }
2965                         
2966         if(size>2) {
2967           /* 24-bits, result in PRODH:PRODL:WREG */
2968           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2969         }
2970                         
2971         if(size>3) {
2972           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2973           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2974         }
2975       
2976       } else {
2977         /* >32-bits, result on stack, and FSR0 points to beginning.
2978          * Fix stack when done */
2979         /* FIXME FIXME */
2980 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2981         while (size--) {
2982 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2983 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2984                 
2985           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2986           GpsuedoStkPtr++;
2987         }
2988                         
2989         /* fix stack */
2990         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2991         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2992         if(STACK_MODEL_LARGE) {
2993           emitSKPNC;
2994           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2995         }
2996       }                 
2997     } else {
2998       int areg = 0;             /* matching argument register */
2999       
3000 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3001       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3002
3003
3004       /* its called from genReceive (probably) -- VR */
3005       /* I hope this code will not be called from somewhere else in the future! 
3006        * We manually set the pseudo stack pointer in genReceive. - dw
3007        */
3008       if(!GpsuedoStkPtr && _G.useWreg) {
3009 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3010
3011         /* The last byte in the assignment is in W */
3012         if(areg <= GpsuedoStkPtr) {
3013           size--;
3014           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3015           offset++;
3016 //          debugf("receive from WREG\n", 0);
3017         }
3018         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3019       }
3020 //      GpsuedoStkPtr++;
3021       _G.stack_lat = AOP_SIZE(oper)-1;
3022
3023       while (size) {
3024         size--;
3025         GpsuedoStkPtr++;
3026         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3027 //        debugf("receive from STACK\n", 0);
3028         offset++;
3029       }
3030     }
3031 }
3032
3033
3034 /*-----------------------------------------------------------------*/
3035 /* genIpush - generate code for pushing this gets a little complex */
3036 /*-----------------------------------------------------------------*/
3037 static void genIpush (iCode *ic)
3038 {
3039 //  int size, offset=0;
3040
3041   FENTRY;
3042   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3043
3044   if(ic->parmPush) {
3045     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3046
3047     /* send to stack as normal */
3048     addSet(&_G.sendSet,ic);
3049 //    addSetHead(&_G.sendSet,ic);
3050     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3051   }
3052
3053         
3054 #if 0
3055     int size, offset = 0 ;
3056     char *l;
3057
3058
3059     /* if this is not a parm push : ie. it is spill push 
3060     and spill push is always done on the local stack */
3061     if (!ic->parmPush) {
3062
3063         /* and the item is spilt then do nothing */
3064         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3065             return ;
3066
3067         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3068         size = AOP_SIZE(IC_LEFT(ic));
3069         /* push it on the stack */
3070         while(size--) {
3071             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3072             if (*l == '#') {
3073                 MOVA(l);
3074                 l = "acc";
3075             }
3076             pic16_emitcode("push","%s",l);
3077         }
3078         return ;        
3079     }
3080
3081     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3082 #endif
3083 }
3084
3085 /*-----------------------------------------------------------------*/
3086 /* genIpop - recover the registers: can happen only for spilling   */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpop (iCode *ic)
3089 {
3090   FENTRY;
3091   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3092 #if 0
3093     int size,offset ;
3094
3095
3096     /* if the temp was not pushed then */
3097     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3098         return ;
3099
3100     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3101     size = AOP_SIZE(IC_LEFT(ic));
3102     offset = (size-1);
3103     while (size--) 
3104         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3105                                    FALSE,TRUE));
3106
3107     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3108 #endif
3109 }
3110
3111 #if 0
3112 /*-----------------------------------------------------------------*/
3113 /* unsaverbank - restores the resgister bank from stack            */
3114 /*-----------------------------------------------------------------*/
3115 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3116 {
3117   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3118 #if 0
3119     int i;
3120     asmop *aop ;
3121     regs *r = NULL;
3122
3123     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3124     if (popPsw) {
3125         if (options.useXstack) {
3126             aop = newAsmop(0);
3127             r = getFreePtr(ic,&aop,FALSE);
3128             
3129             
3130             pic16_emitcode("mov","%s,_spx",r->name);
3131             pic16_emitcode("movx","a,@%s",r->name);
3132             pic16_emitcode("mov","psw,a");
3133             pic16_emitcode("dec","%s",r->name);
3134             
3135         }else
3136             pic16_emitcode ("pop","psw");
3137     }
3138
3139     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3140         if (options.useXstack) {       
3141             pic16_emitcode("movx","a,@%s",r->name);
3142             //pic16_emitcode("mov","(%s+%d),a",
3143             //       regspic16[i].base,8*bank+regspic16[i].offset);
3144             pic16_emitcode("dec","%s",r->name);
3145
3146         } else 
3147           pic16_emitcode("pop",""); //"(%s+%d)",
3148         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3149     }
3150
3151     if (options.useXstack) {
3152
3153         pic16_emitcode("mov","_spx,%s",r->name);
3154         pic16_freeAsmop(NULL,aop,ic,TRUE);
3155
3156     }
3157 #endif 
3158 }
3159
3160 /*-----------------------------------------------------------------*/
3161 /* saverbank - saves an entire register bank on the stack          */
3162 /*-----------------------------------------------------------------*/
3163 static void saverbank (int bank, iCode *ic, bool pushPsw)
3164 {
3165   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3166 #if 0
3167     int i;
3168     asmop *aop ;
3169     regs *r = NULL;
3170
3171     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3172     if (options.useXstack) {
3173
3174         aop = newAsmop(0);
3175         r = getFreePtr(ic,&aop,FALSE);  
3176         pic16_emitcode("mov","%s,_spx",r->name);
3177
3178     }
3179
3180     for (i = 0 ; i < pic16_nRegs ;i++) {
3181         if (options.useXstack) {
3182             pic16_emitcode("inc","%s",r->name);
3183             //pic16_emitcode("mov","a,(%s+%d)",
3184             //         regspic16[i].base,8*bank+regspic16[i].offset);
3185             pic16_emitcode("movx","@%s,a",r->name);           
3186         } else 
3187           pic16_emitcode("push","");// "(%s+%d)",
3188                      //regspic16[i].base,8*bank+regspic16[i].offset);
3189     }
3190     
3191     if (pushPsw) {
3192         if (options.useXstack) {
3193             pic16_emitcode("mov","a,psw");
3194             pic16_emitcode("movx","@%s,a",r->name);     
3195             pic16_emitcode("inc","%s",r->name);
3196             pic16_emitcode("mov","_spx,%s",r->name);       
3197             pic16_freeAsmop (NULL,aop,ic,TRUE);
3198             
3199         } else
3200             pic16_emitcode("push","psw");
3201         
3202         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3203     }
3204     ic->bankSaved = 1;
3205 #endif
3206 }
3207 #endif  /* 0 */
3208
3209
3210 static int wparamCmp(void *p1, void *p2)
3211 {
3212   return (!strcmp((char *)p1, (char *)p2));
3213 }
3214
3215 int inWparamList(char *s)
3216 {
3217   return isinSetWith(wparamList, s, wparamCmp);
3218
3219
3220
3221 /*-----------------------------------------------------------------*/
3222 /* genCall - generates a call statement                            */
3223 /*-----------------------------------------------------------------*/
3224 static void genCall (iCode *ic)
3225 {
3226   sym_link *ftype;   
3227   int stackParms=0;
3228   int use_wreg=0;
3229   int inwparam=0;
3230   char *fname;
3231   
3232     FENTRY;
3233
3234     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3235     /* if caller saves & we have not saved then */
3236 //    if (!ic->regsSaved)
3237 //      saveRegisters(ic);
3238
3239         /* initialise stackParms for IPUSH pushes */
3240 //      stackParms = psuedoStkPtr;
3241 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3242     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3243     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3244
3245 #if 0
3246     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3247 #endif
3248
3249     /* if send set is not empty the assign */
3250     if (_G.sendSet) {
3251       iCode *sic;
3252       int psuedoStkPtr=-1; 
3253       int firstTimeThruLoop = 1;
3254
3255
3256         /* reverse sendSet if function is not reentrant */
3257         if(!IFFUNC_ISREENT(ftype))
3258           _G.sendSet = reverseSet(_G.sendSet);
3259
3260         /* First figure how many parameters are getting passed */
3261         stackParms = 0;
3262         use_wreg = 0;
3263         
3264         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3265           int size;
3266 //          int offset = 0;
3267
3268             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3269             size = AOP_SIZE(IC_LEFT(sic));
3270
3271             stackParms += size;
3272
3273             /* pass the last byte through WREG */
3274             if(inwparam) {
3275
3276               while (size--) {
3277                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3278                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3279                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3280
3281                 if(!firstTimeThruLoop) {
3282                   /* If this is not the first time we've been through the loop
3283                    * then we need to save the parameter in a temporary
3284                    * register. The last byte of the last parameter is
3285                    * passed in W. */
3286
3287                   pushw();
3288 //                  --psuedoStkPtr;             // sanity check
3289                   use_wreg = 1;
3290                 }
3291                 
3292                 firstTimeThruLoop=0;
3293
3294                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3295
3296 //                offset++;
3297               }
3298             } else {
3299               /* all arguments are passed via stack */
3300               use_wreg = 0;
3301
3302               while (size--) {
3303                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3304                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3305                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3306
3307 //                pushaop(AOP(IC_LEFT(sic)), size);
3308                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3309                 pushw();
3310               }
3311             }
3312
3313             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3314           }
3315
3316           if(inwparam) {
3317             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3318               pushw();  /* save last parameter to stack if functions has varargs */
3319               use_wreg = 0;
3320             } else
3321               use_wreg = 1;
3322           } else use_wreg = 0;
3323
3324           _G.stackRegSet = _G.sendSet;
3325           _G.sendSet = NULL;
3326     }
3327
3328     /* make the call */
3329     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3330
3331     GpsuedoStkPtr=0;
3332     
3333     /* if we need to assign a result value */
3334     if ((IS_ITEMP(IC_RESULT(ic))
3335           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3336               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3337         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3338
3339       _G.accInUse++;
3340       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3341       _G.accInUse--;
3342
3343       assignResultValue(IC_RESULT(ic), 1);
3344
3345       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3347                 
3348       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3349     }
3350
3351     if(!stackParms && ic->parmBytes) {
3352       stackParms = ic->parmBytes;
3353     }
3354       
3355     stackParms -= use_wreg;
3356     
3357     if(stackParms>0) {
3358       if(stackParms == 1) {
3359         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3360       } else {
3361         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3362         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3363       }
3364       if(STACK_MODEL_LARGE) {
3365         emitSKPNC;
3366         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3367       }
3368     }
3369
3370 #if 0
3371     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3372 #endif
3373
3374     /* adjust the stack for parameters if required */
3375 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3376
3377 #if 0
3378       /* if register bank was saved then pop them */
3379       if (ic->bankSaved)
3380         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3381
3382       /* if we hade saved some registers then unsave them */
3383       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3384         unsaveRegisters (ic);
3385 #endif
3386 }
3387
3388
3389
3390 /*-----------------------------------------------------------------*/
3391 /* genPcall - generates a call by pointer statement                */
3392 /*            new version, created from genCall - HJD              */
3393 /*-----------------------------------------------------------------*/
3394 static void genPcall (iCode *ic)
3395 {
3396   sym_link *ftype, *fntype;
3397   int stackParms=0;
3398   symbol *retlbl = newiTempLabel(NULL);
3399   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3400   
3401     FENTRY;
3402
3403     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3404     fntype = operandType( IC_LEFT(ic) )->next;
3405
3406     /* if send set is not empty the assign */
3407     if (_G.sendSet) {
3408       iCode *sic;
3409       int psuedoStkPtr=-1; 
3410
3411       /* reverse sendSet if function is not reentrant */
3412       if(!IFFUNC_ISREENT(fntype))
3413         _G.sendSet = reverseSet(_G.sendSet);
3414
3415       stackParms = 0;
3416       
3417       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3418         int size;
3419
3420           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3421           size = AOP_SIZE(IC_LEFT(sic));
3422           stackParms += size;
3423
3424           /* all parameters are passed via stack, since WREG is clobbered
3425            * by the calling sequence */
3426           while (size--) {
3427             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3428             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3429             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3430
3431             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3432             pushw();
3433           }
3434
3435           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3436       }
3437
3438       _G.stackRegSet = _G.sendSet;
3439       _G.sendSet = NULL;
3440     }
3441
3442     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3443
3444     // push return address
3445     // push $ on return stack, then replace with retlbl
3446
3447     /* Thanks to Thorsten Klose for pointing out that the following
3448      * snippet should be interrupt safe */
3449     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3450     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3451
3452     pic16_emitpcodeNULLop(POC_PUSH);
3453
3454     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3455     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3456     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3457     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3458     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3459     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3460
3461
3462     /* restore interrupt control register */
3463     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3465
3466     /* make the call by writing the pointer into pc */
3467     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3468     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3469
3470     // note: MOVFF to PCL not allowed
3471     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3472     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3473
3474
3475     /* return address is here: (X) */
3476     pic16_emitpLabelFORCE(retlbl->key);
3477
3478     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3479
3480     GpsuedoStkPtr=0;
3481     /* if we need assign a result value */
3482     if ((IS_ITEMP(IC_RESULT(ic))
3483           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3484               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3485         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3486
3487       _G.accInUse++;
3488       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3489       _G.accInUse--;
3490
3491       assignResultValue(IC_RESULT(ic), 1);
3492
3493       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3494               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3495                 
3496       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3497     }
3498
3499 //    stackParms -= use_wreg;
3500     
3501     if(stackParms>0) {
3502       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3503       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3504       if(STACK_MODEL_LARGE) {
3505         emitSKPNC;
3506         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3507       }
3508     }
3509 }
3510
3511 /*-----------------------------------------------------------------*/
3512 /* resultRemat - result  is rematerializable                       */
3513 /*-----------------------------------------------------------------*/
3514 static int resultRemat (iCode *ic)
3515 {
3516   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3517   if (SKIP_IC(ic) || ic->op == IFX)
3518     return 0;
3519
3520   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3521     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3522     if (sym->remat && !POINTER_SET(ic)) 
3523       return 1;
3524   }
3525
3526   return 0;
3527 }
3528
3529 #if defined(__BORLANDC__) || defined(_MSC_VER)
3530 #define STRCASECMP stricmp
3531 #else
3532 #define STRCASECMP strcasecmp
3533 #endif
3534
3535 #if 0
3536 /*-----------------------------------------------------------------*/
3537 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3538 /*-----------------------------------------------------------------*/
3539 static bool inExcludeList(char *s)
3540 {
3541   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3542     int i =0;
3543     
3544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3545     if (options.excludeRegs[i] &&
3546     STRCASECMP(options.excludeRegs[i],"none") == 0)
3547         return FALSE ;
3548
3549     for ( i = 0 ; options.excludeRegs[i]; i++) {
3550         if (options.excludeRegs[i] &&
3551         STRCASECMP(s,options.excludeRegs[i]) == 0)
3552             return TRUE;
3553     }
3554     return FALSE ;
3555 }
3556 #endif
3557
3558 /*-----------------------------------------------------------------*/
3559 /* genFunction - generated code for function entry                 */
3560 /*-----------------------------------------------------------------*/
3561 static void genFunction (iCode *ic)
3562 {
3563   symbol *sym;
3564   sym_link *ftype;
3565   
3566     FENTRY;
3567     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3568
3569     pic16_labelOffset += (max_key+4);
3570     max_key=0;
3571     GpsuedoStkPtr=0;
3572     _G.nRegsSaved = 0;
3573         
3574     ftype = operandType(IC_LEFT(ic));
3575     sym = OP_SYMBOL(IC_LEFT(ic));
3576
3577     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3578       /* create an absolute section at the interrupt vector:
3579        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3580       symbol *asym;
3581       char asymname[128];
3582       pBlock *apb;
3583
3584
3585 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3586
3587 #if 0
3588         {
3589           int i, found=-1;
3590
3591             sym = OP_SYMBOL( IC_LEFT(ic));
3592             for(i=0;i<=2;i++) {
3593               if(interrupts[i]->name
3594                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3595                   found = i;
3596                   break;
3597               }
3598             }
3599                         
3600             if(found == -1) {
3601               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3602                             __FILE__, __LINE__, sym->name);
3603 //              assert( 0 );
3604             }
3605             _G.interruptvector = found;
3606         }
3607 #endif
3608
3609         if(FUNC_INTNO(sym->type) == 256)
3610           sprintf(asymname, "ivec_%s", sym->name);
3611         else
3612           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3613         asym = newSymbol(asymname, 0);
3614
3615         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3616         pic16_addpBlock( apb );
3617
3618         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3619         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3620         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3621                 
3622         /* mark the end of this tiny function */
3623         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3624
3625         {
3626           absSym *abSym;
3627
3628             abSym = Safe_calloc(1, sizeof(absSym));
3629             strcpy(abSym->name, asymname);
3630
3631             switch( FUNC_INTNO(sym->type) ) {
3632               case 0: abSym->address = 0x000000; break;
3633               case 1: abSym->address = 0x000008; break;
3634               case 2: abSym->address = 0x000018; break;
3635               
3636               default:
3637                 abSym->address = -1; break;
3638             }
3639
3640             /* relocate interrupt vectors if needed */
3641             if(abSym->address != -1)
3642               abSym->address += pic16_options.ivt_loc;
3643
3644             addSet(&absSymSet, abSym);
3645         }
3646     }
3647
3648     /* create the function header */
3649     pic16_emitcode(";","-----------------------------------------");
3650     pic16_emitcode(";"," function %s",sym->name);
3651     pic16_emitcode(";","-----------------------------------------");
3652
3653     pic16_emitcode("","%s:",sym->rname);
3654     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3655
3656
3657     {
3658       absSym *ab;
3659
3660         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3661           if(!strcmp(ab->name, sym->rname)) {
3662             pic16_pBlockConvert2Absolute(pb);
3663             break;
3664           }
3665         }
3666     }
3667
3668
3669     if(IFFUNC_ISNAKED(ftype)) {
3670       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3671       return;
3672     }
3673         
3674     /* if critical function then turn interrupts off */
3675     if (IFFUNC_ISCRITICAL(ftype)) {
3676       //pic16_emitcode("clr","ea");
3677     }
3678
3679     _G.fregsUsed = sym->regsUsed;
3680
3681     /* if this is an interrupt service routine then
3682      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3683     if (IFFUNC_ISISR(sym->type)) {
3684         _G.usefastretfie = 1;   /* use shadow registers by default */
3685         
3686         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3687         if(!FUNC_ISSHADOWREGS(sym->type)) {
3688           /* do not save WREG,STATUS,BSR for high priority interrupts
3689            * because they are stored in the hardware shadow registers already */
3690           _G.usefastretfie = 0;
3691           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3692           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3693           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3694         }
3695
3696         /* these should really be optimized somehow, because not all
3697          * interrupt handlers modify them */
3698         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3699         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3700         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3701         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3702         
3703 //        pic16_pBlockConvert2ISR(pb);
3704                 
3705     }
3706
3707     /* emit code to setup stack frame if user enabled,
3708      * and function is not main() */
3709          
3710     //fprintf(stderr, "function name: %s\n", sym->name);
3711     if(strcmp(sym->name, "main")) {
3712       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3713         /* setup the stack frame */
3714         if(STACK_MODEL_LARGE)
3715           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3716         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3717
3718         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3719         if(STACK_MODEL_LARGE)
3720           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3721       }
3722     }
3723
3724     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3725           && sym->stack) {
3726
3727       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3728
3729       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3730       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3731       emitSKPC;
3732       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3733     }
3734           
3735     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3736       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3737         _G.useWreg = 0;
3738       else
3739         _G.useWreg = 1;
3740     } else
3741       _G.useWreg = 0;
3742
3743     /* if callee-save to be used for this function
3744      * then save the registers being used in this function */
3745 //    if (IFFUNC_CALLEESAVES(sym->type))
3746     {
3747       int i;
3748
3749         /* if any registers used */
3750         if (sym->regsUsed) {
3751           /* save the registers used */
3752           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3753           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3754           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3755             if (bitVectBitValue(sym->regsUsed,i)) {
3756               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3757               _G.nRegsSaved++;
3758
3759               if(!pic16_regWithIdx(i)->wasUsed) {
3760                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3761                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3762                 pic16_regWithIdx(i)->wasUsed = 1;
3763               }
3764             }
3765           }
3766           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3767         }
3768     }
3769         
3770     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3771 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3772 }
3773
3774 /*-----------------------------------------------------------------*/
3775 /* genEndFunction - generates epilogue for functions               */
3776 /*-----------------------------------------------------------------*/
3777 static void genEndFunction (iCode *ic)
3778 {
3779   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3780
3781     FENTRY;
3782
3783     if(IFFUNC_ISNAKED(sym->type)) {
3784       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3785       return;
3786     }
3787
3788     _G.stack_lat = 0;
3789
3790     /* add code for ISCRITICAL */
3791     if(IFFUNC_ISCRITICAL(sym->type)) {
3792       /* if critical function, turn on interrupts */
3793       
3794       /* TODO: add code here -- VR */
3795     }
3796     
3797 //    sym->regsUsed = _G.fregsUsed;
3798     
3799     /* now we need to restore the registers */
3800     /* if any registers used */
3801     if (sym->regsUsed) {
3802       int i;
3803
3804         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3805         /* restore registers used */
3806         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3807         for ( i = sym->regsUsed->size; i >= 0; i--) {
3808           if (bitVectBitValue(sym->regsUsed,i)) {
3809             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3810             _G.nRegsSaved--;
3811           }
3812         }
3813         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3814
3815     }
3816
3817     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3818           && sym->stack) {
3819       if (sym->stack == 1) {
3820         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3821         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3822       } else {
3823         // we have to add more than one...
3824         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3825         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3826         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3827         emitSKPNC;
3828         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3829         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3830         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3831       }
3832     }
3833
3834     if(strcmp(sym->name, "main")) {
3835       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3836         /* restore stack frame */
3837         if(STACK_MODEL_LARGE)
3838           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3839         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3840       }
3841     }
3842
3843     _G.useWreg = 0;
3844
3845     if (IFFUNC_ISISR(sym->type)) {
3846       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3847       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3848       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3849       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3850
3851       if(!FUNC_ISSHADOWREGS(sym->type)) {
3852         /* do not restore interrupt vector for WREG,STATUS,BSR
3853          * for high priority interrupt, see genFunction */
3854         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3855         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3856         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3857       }
3858 //      _G.interruptvector = 0;         /* sanity check */
3859
3860
3861       /* if debug then send end of function */
3862 /*      if (options.debug && currFunc)  */
3863       if (currFunc) {
3864         debugFile->writeEndFunction (currFunc, ic, 1);
3865       }
3866         
3867       if(_G.usefastretfie)
3868         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3869       else
3870         pic16_emitpcodeNULLop(POC_RETFIE);
3871
3872       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3873       
3874       _G.usefastretfie = 0;
3875       return;
3876     }
3877
3878     if (IFFUNC_ISCRITICAL(sym->type)) {
3879       pic16_emitcode("setb","ea");
3880     }
3881
3882     /* if debug then send end of function */
3883     if (currFunc) {
3884       debugFile->writeEndFunction (currFunc, ic, 1);
3885     }
3886
3887     /* insert code to restore stack frame, if user enabled it
3888      * and function is not main() */
3889          
3890
3891     pic16_emitpcodeNULLop(POC_RETURN);
3892
3893     /* Mark the end of a function */
3894     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3895 }
3896
3897
3898 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3899 {
3900   unsigned long lit=1;
3901  
3902   // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3903   if(AOP_TYPE(op) == AOP_LIT) {
3904     if(!IS_FLOAT(operandType( op ))) {
3905       lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3906     } else {
3907       union {
3908         unsigned long lit_int;
3909         float lit_float;
3910       } info;
3911         
3912       /* take care if literal is a float */
3913       info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3914       lit = info.lit_int;
3915     }
3916   }
3917
3918   if (is_LitOp(op)) {
3919       if(lit == 0) {
3920         pic16_emitpcode(POC_CLRF, dest);
3921       } else {
3922         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3923         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3924       }
3925   } else {
3926     if(dest->type == PO_WREG && (offset == 0)) {
3927       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3928       return;
3929     }
3930     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3931   }
3932 }
3933
3934 /*-----------------------------------------------------------------*/
3935 /* genRet - generate code for return statement                     */
3936 /*-----------------------------------------------------------------*/
3937 static void genRet (iCode *ic)
3938 {
3939   int size;
3940   operand *left;
3941
3942     FENTRY;
3943         /* if we have no return value then
3944          * just generate the "ret" */
3945         
3946         if (!IC_LEFT(ic)) 
3947                 goto jumpret;       
3948     
3949         /* we have something to return then
3950          * move the return value into place */
3951         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3952         size = AOP_SIZE(IC_LEFT(ic));
3953
3954         if(size <= 4) {
3955                 if(size>3) {
3956                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3957 //                      pic16_emitpcode(POC_MOVFF,
3958 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3959                 }
3960                 if(size>2) {
3961                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3962 //                      pic16_emitpcode(POC_MOVFF,
3963 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3964                 }
3965                 if(size>1) {
3966                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3967 //                      pic16_emitpcode(POC_MOVFF,
3968 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3969                 }
3970
3971 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3972
3973                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3974 //              pic16_emitpcode(POC_MOVFF,
3975 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3976
3977         } else {
3978                 /* >32-bits, setup stack and FSR0 */
3979                 while (size--) {
3980 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3981 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3982
3983                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3984
3985 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3986                         GpsuedoStkPtr++;
3987                 }
3988                         
3989                 /* setup FSR0 */
3990                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3991                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3992
3993                 if(STACK_MODEL_LARGE) {
3994                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3996                 } else {
3997                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3998                 }
3999         }
4000                                 
4001 #if 0
4002         /* old code, left here for reference -- VR */    
4003         while (size--) {
4004           char *l ;
4005
4006                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4007                         /* #NOCHANGE */
4008                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4009                         pic16_emitpcomment("push %s",l);
4010                         pushed++;
4011                 } else {
4012                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4013                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4014                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4015                         
4016                         if (strcmp(fReturn[offset],l)) {
4017                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4018                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4019                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4020                                 } else {
4021                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4022                                 }
4023                                 
4024                                 if(size) {
4025                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4026                                 }
4027                                 offset++;
4028                         }
4029                 }
4030         }    
4031
4032         if (pushed) {
4033                 while(pushed) {
4034                         pushed--;
4035                         if (strcmp(fReturn[pushed],"a"))
4036                                 pic16_emitcode("pop",fReturn[pushed]);
4037                         else
4038                                 pic16_emitcode("pop","acc");
4039                 }
4040         }
4041 #endif
4042
4043
4044         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4045     
4046 jumpret:
4047         /* generate a jump to the return label
4048          * if the next is not the return statement */
4049         if (!(ic->next && ic->next->op == LABEL
4050                 && IC_LABEL(ic->next) == returnLabel)) {
4051         
4052                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4053                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4054         }
4055 }
4056
4057 /*-----------------------------------------------------------------*/
4058 /* genLabel - generates a label                                    */
4059 /*-----------------------------------------------------------------*/
4060 static void genLabel (iCode *ic)
4061 {
4062   FENTRY;
4063
4064   /* special case never generate */
4065   if (IC_LABEL(ic) == entryLabel)
4066     return ;
4067
4068   pic16_emitpLabel(IC_LABEL(ic)->key);
4069 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4070 }
4071
4072 /*-----------------------------------------------------------------*/
4073 /* genGoto - generates a goto                                      */
4074 /*-----------------------------------------------------------------*/
4075 //tsd
4076 static void genGoto (iCode *ic)
4077 {
4078   FENTRY;
4079   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4080 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4081 }
4082
4083
4084 /*-----------------------------------------------------------------*/
4085 /* genMultbits :- multiplication of bits                           */
4086 /*-----------------------------------------------------------------*/
4087 static void genMultbits (operand *left, 
4088                          operand *right, 
4089                          operand *result)
4090 {
4091   FENTRY;
4092
4093   if(!pic16_sameRegs(AOP(result),AOP(right)))
4094     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4095
4096   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4097   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4098   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4099
4100 }
4101
4102
4103 /*-----------------------------------------------------------------*/
4104 /* genMultOneByte : 8 bit multiplication & division                */
4105 /*-----------------------------------------------------------------*/
4106 static void genMultOneByte (operand *left,
4107                             operand *right,
4108                             operand *result)
4109 {
4110
4111   FENTRY;
4112   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4113   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4114
4115   /* (if two literals, the value is computed before) */
4116   /* if one literal, literal on the right */
4117   if (AOP_TYPE(left) == AOP_LIT){
4118     operand *t = right;
4119     right = left;
4120     left = t;
4121   }
4122
4123         /* size is already checked in genMult == 1 */
4124 //      size = AOP_SIZE(result);
4125
4126         if (AOP_TYPE(right) == AOP_LIT){
4127                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4128                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4129                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4130                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4131         } else {
4132                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4133                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4134                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4135                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4136         }
4137         
4138         pic16_genMult8X8_8 (left, right,result);
4139 }
4140
4141 /*-----------------------------------------------------------------*/
4142 /* genMultOneWord : 16 bit multiplication                          */
4143 /*-----------------------------------------------------------------*/
4144 static void genMultOneWord (operand *left,
4145                             operand *right,
4146                             operand *result)
4147 {
4148   FENTRY;
4149   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4150   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4151
4152   /* (if two literals, the value is computed before)
4153    * if one literal, literal on the right */
4154   if (AOP_TYPE(left) == AOP_LIT){
4155     operand *t = right;
4156     right = left;
4157     left = t;
4158   }
4159
4160   /* size is checked already == 2 */
4161 //  size = AOP_SIZE(result);
4162
4163   if (AOP_TYPE(right) == AOP_LIT) {
4164     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4165       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4166       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4167       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4168   } else {
4169     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4170       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4171       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4172       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4173   }
4174         
4175   pic16_genMult16X16_16(left, right,result);
4176 }
4177
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneLong : 32 bit multiplication                          */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneLong (operand *left,
4182                             operand *right,
4183                             operand *result)
4184 {
4185   FENTRY;
4186   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4187   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4188
4189   /* (if two literals, the value is computed before)
4190    * if one literal, literal on the right */
4191   if (AOP_TYPE(left) == AOP_LIT){
4192     operand *t = right;
4193     right = left;
4194     left = t;
4195   }
4196
4197   /* size is checked already == 4 */
4198 //  size = AOP_SIZE(result);
4199
4200   if (AOP_TYPE(right) == AOP_LIT) {
4201     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4202         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4203         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4204         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4205   } else {
4206     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4207         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4208         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4209         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210   }
4211         
4212   pic16_genMult32X32_32(left, right,result);
4213 }
4214
4215
4216
4217 /*-----------------------------------------------------------------*/
4218 /* genMult - generates code for multiplication                     */
4219 /*-----------------------------------------------------------------*/
4220 static void genMult (iCode *ic)
4221 {
4222   operand *left = IC_LEFT(ic);
4223   operand *right = IC_RIGHT(ic);
4224   operand *result= IC_RESULT(ic);   
4225
4226     FENTRY;
4227         /* assign the amsops */
4228         pic16_aopOp (left,ic,FALSE);
4229         pic16_aopOp (right,ic,FALSE);
4230         pic16_aopOp (result,ic,TRUE);
4231
4232         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4233
4234         /* special cases first *
4235         * both are bits */
4236         if (AOP_TYPE(left) == AOP_CRY
4237                 && AOP_TYPE(right)== AOP_CRY) {
4238                 genMultbits(left,right,result);
4239           goto release ;
4240         }
4241
4242         /* if both are of size == 1 */
4243         if(AOP_SIZE(left) == 1
4244                 && AOP_SIZE(right) == 1) {
4245                 genMultOneByte(left,right,result);
4246           goto release ;
4247         }
4248
4249         /* if both are of size == 2 */
4250         if(AOP_SIZE(left) == 2
4251                 && AOP_SIZE(right) == 2) {
4252                 genMultOneWord(left, right, result);
4253           goto release;
4254         }
4255         
4256         /* if both are of size == 4 */
4257         if(AOP_SIZE(left) == 4
4258                 && AOP_SIZE(right) == 4) {
4259                 genMultOneLong(left, right, result);
4260           goto release;
4261         }
4262         
4263         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4264
4265
4266         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4267         /* should have been converted to function call */
4268         assert(0) ;
4269
4270 release :
4271         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273         pic16_freeAsmop(result,NULL,ic,TRUE); 
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genDivbits :- division of bits                                  */
4278 /*-----------------------------------------------------------------*/
4279 static void genDivbits (operand *left, 
4280                         operand *right, 
4281                         operand *result)
4282 {
4283   char *l;
4284
4285     FENTRY;
4286     /* the result must be bit */    
4287     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4288     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4289
4290     MOVA(l);    
4291
4292     pic16_emitcode("div","ab");
4293     pic16_emitcode("rrc","a");
4294     pic16_aopPut(AOP(result),"c",0);
4295 }
4296
4297 /*-----------------------------------------------------------------*/
4298 /* genDivOneByte : 8 bit division                                  */
4299 /*-----------------------------------------------------------------*/
4300 static void genDivOneByte (operand *left,
4301                            operand *right,
4302                            operand *result)
4303 {
4304   sym_link *opetype = operandType(result);
4305   char *l ;
4306   symbol *lbl ;
4307   int size,offset;
4308
4309         /* result = divident / divisor
4310          * - divident may be a register or a literal,
4311          * - divisor may be a register or a literal,
4312          * so there are 3 cases (literal / literal is optimized
4313          * by the front-end) to handle.
4314          * In addition we must handle signed and unsigned, which
4315          * result in 6 final different cases -- VR */
4316
4317     FENTRY;
4318     
4319     size = AOP_SIZE(result) - 1;
4320     offset = 1;
4321     /* signed or unsigned */
4322     if (SPEC_USIGN(opetype)) {
4323       pCodeOp *pct1,    /* count */
4324                 *pct2,  /* reste */
4325                 *pct3;  /* temp */
4326       symbol *label1, *label2, *label3;;
4327
4328
4329         /* unsigned is easy */
4330
4331         pct1 = pic16_popGetTempReg(1);
4332         pct2 = pic16_popGetTempReg(1);
4333         pct3 = pic16_popGetTempReg(1);
4334         
4335         label1 = newiTempLabel(NULL);
4336         label2 = newiTempLabel(NULL);
4337         label3 = newiTempLabel(NULL);
4338
4339         /* the following algorithm is extracted from divuint.c */
4340
4341         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4342         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4343         
4344         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4345
4346         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4347         
4348         pic16_emitpLabel(label1->key);
4349         
4350         emitCLRC;
4351         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4352
4353
4354         emitCLRC;
4355         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4356         
4357
4358         emitSKPNC;
4359         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4360         
4361         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4362         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4363         
4364         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4365         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4366         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4367         
4368         pic16_emitpLabel( label3->key );
4369         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4370         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4371         
4372         
4373
4374         pic16_emitpLabel(label2->key);
4375         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4376         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4377         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4378         
4379         /* result is in wreg */
4380         if(AOP_TYPE(result) != AOP_ACC)
4381                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4382
4383         pic16_popReleaseTempReg( pct3, 1);
4384         pic16_popReleaseTempReg( pct2, 1);
4385         pic16_popReleaseTempReg( pct1, 1);
4386
4387         return ;
4388     }
4389
4390     /* signed is a little bit more difficult */
4391
4392     /* save the signs of the operands */
4393     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4394     MOVA(l);    
4395     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4396     pic16_emitcode("push","acc"); /* save it on the stack */
4397
4398     /* now sign adjust for both left & right */
4399     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4400     MOVA(l);       
4401     lbl = newiTempLabel(NULL);
4402     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4403     pic16_emitcode("cpl","a");   
4404     pic16_emitcode("inc","a");
4405     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4406     pic16_emitcode("mov","b,a");
4407
4408     /* sign adjust left side */
4409     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4410     MOVA(l);
4411
4412     lbl = newiTempLabel(NULL);
4413     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4414     pic16_emitcode("cpl","a");
4415     pic16_emitcode("inc","a");
4416     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417
4418     /* now the division */
4419     pic16_emitcode("div","ab");
4420     /* we are interested in the lower order
4421     only */
4422     pic16_emitcode("mov","b,a");
4423     lbl = newiTempLabel(NULL);
4424     pic16_emitcode("pop","acc");   
4425     /* if there was an over flow we don't 
4426     adjust the sign of the result */
4427     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4428     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4429     CLRC;
4430     pic16_emitcode("clr","a");
4431     pic16_emitcode("subb","a,b");
4432     pic16_emitcode("mov","b,a");
4433     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4434
4435     /* now we are done */
4436     pic16_aopPut(AOP(result),"b",0);
4437     if(size > 0){
4438         pic16_emitcode("mov","c,b.7");
4439         pic16_emitcode("subb","a,acc");   
4440     }
4441     while (size--)
4442         pic16_aopPut(AOP(result),"a",offset++);
4443
4444 }
4445
4446 /*-----------------------------------------------------------------*/
4447 /* genDiv - generates code for division                            */
4448 /*-----------------------------------------------------------------*/
4449 static void genDiv (iCode *ic)
4450 {
4451     operand *left = IC_LEFT(ic);
4452     operand *right = IC_RIGHT(ic);
4453     operand *result= IC_RESULT(ic);   
4454
4455
4456         /* Division is a very lengthy algorithm, so it is better
4457          * to call support routines than inlining algorithm.
4458          * Division functions written here just in case someone
4459          * wants to inline and not use the support libraries -- VR */
4460
4461     FENTRY;
4462     
4463     /* assign the amsops */
4464     pic16_aopOp (left,ic,FALSE);
4465     pic16_aopOp (right,ic,FALSE);
4466     pic16_aopOp (result,ic,TRUE);
4467
4468     /* special cases first */
4469     /* both are bits */
4470     if (AOP_TYPE(left) == AOP_CRY &&
4471         AOP_TYPE(right)== AOP_CRY) {
4472         genDivbits(left,right,result);
4473         goto release ;
4474     }
4475
4476     /* if both are of size == 1 */
4477     if (AOP_SIZE(left) == 1 &&
4478         AOP_SIZE(right) == 1 ) {
4479         genDivOneByte(left,right,result);
4480         goto release ;
4481     }
4482
4483     /* should have been converted to function call */
4484     assert(0);
4485 release :
4486     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488     pic16_freeAsmop(result,NULL,ic,TRUE); 
4489 }
4490
4491 /*-----------------------------------------------------------------*/
4492 /* genModbits :- modulus of bits                                   */
4493 /*-----------------------------------------------------------------*/
4494 static void genModbits (operand *left, 
4495                         operand *right, 
4496                         operand *result)
4497 {
4498   char *l;
4499
4500     FENTRY;  
4501     
4502     werror(W_POSSBUG2, __FILE__, __LINE__);
4503     /* the result must be bit */    
4504     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4505     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4506
4507     MOVA(l);       
4508
4509     pic16_emitcode("div","ab");
4510     pic16_emitcode("mov","a,b");
4511     pic16_emitcode("rrc","a");
4512     pic16_aopPut(AOP(result),"c",0);
4513 }
4514
4515 /*-----------------------------------------------------------------*/
4516 /* genModOneByte : 8 bit modulus                                   */
4517 /*-----------------------------------------------------------------*/
4518 static void genModOneByte (operand *left,
4519                            operand *right,
4520                            operand *result)
4521 {
4522   sym_link *opetype = operandType(result);
4523   char *l ;
4524   symbol *lbl ;
4525
4526     FENTRY;
4527     werror(W_POSSBUG2, __FILE__, __LINE__);
4528
4529     /* signed or unsigned */
4530     if (SPEC_USIGN(opetype)) {
4531         /* unsigned is easy */
4532         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4533         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4534         MOVA(l);    
4535         pic16_emitcode("div","ab");
4536         pic16_aopPut(AOP(result),"b",0);
4537         return ;
4538     }
4539
4540     /* signed is a little bit more difficult */
4541
4542     /* save the signs of the operands */
4543     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4544     MOVA(l);
4545
4546     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4547     pic16_emitcode("push","acc"); /* save it on the stack */
4548
4549     /* now sign adjust for both left & right */
4550     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4551     MOVA(l);
4552
4553     lbl = newiTempLabel(NULL);
4554     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4555     pic16_emitcode("cpl","a");   
4556     pic16_emitcode("inc","a");
4557     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4558     pic16_emitcode("mov","b,a"); 
4559
4560     /* sign adjust left side */
4561     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4562     MOVA(l);
4563
4564     lbl = newiTempLabel(NULL);
4565     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4566     pic16_emitcode("cpl","a");   
4567     pic16_emitcode("inc","a");
4568     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4569
4570     /* now the multiplication */
4571     pic16_emitcode("div","ab");
4572     /* we are interested in the lower order
4573     only */
4574     lbl = newiTempLabel(NULL);
4575     pic16_emitcode("pop","acc");   
4576     /* if there was an over flow we don't 
4577     adjust the sign of the result */
4578     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4579     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4580     CLRC ;
4581     pic16_emitcode("clr","a");
4582     pic16_emitcode("subb","a,b");
4583     pic16_emitcode("mov","b,a");
4584     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4585
4586     /* now we are done */
4587     pic16_aopPut(AOP(result),"b",0);
4588
4589 }
4590
4591 /*-----------------------------------------------------------------*/
4592 /* genMod - generates code for division                            */
4593 /*-----------------------------------------------------------------*/
4594 static void genMod (iCode *ic)
4595 {
4596   operand *left = IC_LEFT(ic);
4597   operand *right = IC_RIGHT(ic);
4598   operand *result= IC_RESULT(ic);  
4599
4600     FENTRY;
4601     
4602     /* assign the amsops */
4603     pic16_aopOp (left,ic,FALSE);
4604     pic16_aopOp (right,ic,FALSE);
4605     pic16_aopOp (result,ic,TRUE);
4606
4607     /* special cases first */
4608     /* both are bits */
4609     if (AOP_TYPE(left) == AOP_CRY &&
4610         AOP_TYPE(right)== AOP_CRY) {
4611         genModbits(left,right,result);
4612         goto release ;
4613     }
4614
4615     /* if both are of size == 1 */
4616     if (AOP_SIZE(left) == 1 &&
4617         AOP_SIZE(right) == 1 ) {
4618         genModOneByte(left,right,result);
4619         goto release ;
4620     }
4621
4622     /* should have been converted to function call */
4623     assert(0);
4624
4625 release :
4626     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4627     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628     pic16_freeAsmop(result,NULL,ic,TRUE); 
4629 }
4630
4631 /*-----------------------------------------------------------------*/
4632 /* genIfxJump :- will create a jump depending on the ifx           */
4633 /*-----------------------------------------------------------------*/
4634 /*
4635   note: May need to add parameter to indicate when a variable is in bit space.
4636 */
4637 static void genIfxJump (iCode *ic, char *jval)
4638 {
4639   FENTRY;
4640   
4641     /* if true label then we jump if condition
4642     supplied is true */
4643     if ( IC_TRUE(ic) ) {
4644
4645         if(strcmp(jval,"a") == 0)
4646           emitSKPZ;
4647         else if (strcmp(jval,"c") == 0)
4648           emitSKPNC;
4649         else {
4650           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4651           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4652         }
4653
4654         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4655         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4656
4657     }
4658     else {
4659         /* false label is present */
4660         if(strcmp(jval,"a") == 0)
4661           emitSKPNZ;
4662         else if (strcmp(jval,"c") == 0)
4663           emitSKPC;
4664         else {
4665           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4666           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4667         }
4668
4669         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4670         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4671
4672     }
4673
4674
4675     /* mark the icode as generated */
4676     ic->generated = 1;
4677 }
4678
4679 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4680 {
4681   FENTRY;
4682   
4683     /* if true label then we jump if condition
4684     supplied is true */
4685     if ( IC_TRUE(ic) ) {
4686       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4687       pic16_emitpcode(POC_BTFSC, jop);
4688
4689       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4690       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4691
4692     } else {
4693       /* false label is present */
4694       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4695       pic16_emitpcode(POC_BTFSS, jop);
4696           
4697       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4698       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4699     }
4700
4701
4702     /* mark the icode as generated */
4703     ic->generated = 1;
4704 }
4705
4706 #if 0
4707 // not needed ATM
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genSkip                                                         */
4711 /*-----------------------------------------------------------------*/
4712 static void genSkip(iCode *ifx,int status_bit)
4713 {
4714   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4715   if(!ifx)
4716     return;
4717
4718   if ( IC_TRUE(ifx) ) {
4719     switch(status_bit) {
4720     case 'z':
4721       emitSKPNZ;
4722       break;
4723
4724     case 'c':
4725       emitSKPNC;
4726       break;
4727
4728     case 'd':
4729       emitSKPDC;
4730       break;
4731
4732     }
4733
4734     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4735     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4736
4737   } else {
4738
4739     switch(status_bit) {
4740
4741     case 'z':
4742       emitSKPZ;
4743       break;
4744
4745     case 'c':
4746       emitSKPC;
4747       break;
4748
4749     case 'd':
4750       emitSKPDC;
4751       break;
4752     }
4753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4754     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4755
4756   }
4757
4758 }
4759 #endif
4760
4761 /*-----------------------------------------------------------------*/
4762 /* genSkipc                                                        */
4763 /*-----------------------------------------------------------------*/
4764 static void genSkipc(resolvedIfx *rifx)
4765 {
4766   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4767   
4768   if(!rifx)
4769     return;
4770
4771   if(rifx->condition)
4772     emitSKPC;
4773   else
4774     emitSKPNC;
4775
4776   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4777   rifx->generated = 1;
4778 }
4779
4780 #if !(USE_SIMPLE_GENCMP)
4781 /*-----------------------------------------------------------------*/
4782 /* genSkipz2                                                       */
4783 /*-----------------------------------------------------------------*/
4784 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4785 {
4786   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4787   
4788   if(!rifx)
4789     return;
4790
4791   if( (rifx->condition ^ invert_condition) & 1)
4792     emitSKPZ;
4793   else
4794     emitSKPNZ;
4795
4796   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4797   rifx->generated = 1;
4798 }
4799 #endif
4800
4801 #if 0
4802 /*-----------------------------------------------------------------*/
4803 /* genSkipz                                                        */
4804 /*-----------------------------------------------------------------*/
4805 static void genSkipz(iCode *ifx, int condition)
4806 {
4807   if(!ifx)
4808     return;
4809
4810   if(condition)
4811     emitSKPNZ;
4812   else
4813     emitSKPZ;
4814
4815   if ( IC_TRUE(ifx) )
4816     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4817   else
4818     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4819
4820   if ( IC_TRUE(ifx) )
4821     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4822   else
4823     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4824
4825 }
4826 #endif
4827
4828 #if !(USE_SIMPLE_GENCMP)
4829 /*-----------------------------------------------------------------*/
4830 /* genSkipCond                                                     */
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4833 {
4834   if(!rifx)
4835     return;
4836
4837   if(rifx->condition)
4838     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4839   else
4840     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4841
4842
4843   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4844   rifx->generated = 1;
4845 }
4846 #endif
4847
4848 #if 0
4849 /*-----------------------------------------------------------------*/
4850 /* genChkZeroes :- greater or less than comparison                 */
4851 /*     For each byte in a literal that is zero, inclusive or the   */
4852 /*     the corresponding byte in the operand with W                */
4853 /*     returns true if any of the bytes are zero                   */
4854 /*-----------------------------------------------------------------*/
4855 static int genChkZeroes(operand *op, int lit,  int size)
4856 {
4857
4858   int i;
4859   int flag =1;
4860
4861   while(size--) {
4862     i = (lit >> (size*8)) & 0xff;
4863
4864     if(i==0) {
4865       if(flag) 
4866         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4867       else
4868         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4869       flag = 0;
4870     }
4871   }
4872
4873   return (flag==0);
4874 }
4875 #endif
4876
4877 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4878 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4879 #endif
4880 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4881 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4882
4883 /*-----------------------------------------------------------------*/
4884 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4885 /*                  aop (if it's NOT a literal) or from lit (if    */
4886 /*                  aop is a literal)                              */
4887 /*-----------------------------------------------------------------*/
4888 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4889   if (aop->type == AOP_LIT) {
4890     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4891   } else {
4892     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4893   }
4894 }
4895
4896 /*-----------------------------------------------------------------*/
4897 /* genCmp :- greater or less than comparison                       */
4898 /*-----------------------------------------------------------------*/
4899
4900 #if USE_SIMPLE_GENCMP
4901
4902 /* genCmp performs a left < right comparison, stores
4903  * the outcome in result (if != NULL) and generates
4904  * control flow code for the ifx (if != NULL).
4905  *
4906  * This version leaves in sequences like
4907  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4908  * which should be optmized by the peephole
4909  * optimizer - RN 2005-01-01 */
4910 static void genCmp (operand *left,operand *right,
4911                     operand *result, iCode *ifx, int sign)
4912 {
4913   resolvedIfx rIfx;
4914   int size;
4915   int offs;
4916   symbol *templbl;
4917   operand *dummy;
4918   unsigned long lit;
4919   unsigned long mask;
4920   int performedLt;
4921
4922   FENTRY;
4923   
4924   assert (AOP_SIZE(left) == AOP_SIZE(right));
4925   assert (left && right);
4926
4927   size = AOP_SIZE(right) - 1;
4928   mask = (0x100UL << (size*8)) - 1;
4929   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4930   performedLt = 1;
4931   templbl = NULL;
4932   lit = 0;
4933   
4934   resolveIfx (&rIfx, ifx);
4935
4936   /**********************************************************************
4937    * handle bits - bit compares are promoted to int compares seemingly! *
4938    **********************************************************************/
4939 #if 0
4940   // THIS IS COMPLETELY UNTESTED!
4941   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4942     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4943     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4944     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4945
4946     emitSETC;
4947     // 1 < {0,1} is false --> clear C by skipping the next instruction
4948     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4949     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4950     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4951     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4952     emitCLRC; // only skipped for left=0 && right=1
4953
4954     goto correct_result_in_carry;
4955   } // if
4956 #endif
4957
4958   /*************************************************
4959    * make sure that left is register (or the like) *
4960    *************************************************/
4961   if (!isAOP_REGlike(left)) {
4962     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4963     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4964     #endif
4965     assert (isAOP_LIT(left));
4966     assert (isAOP_REGlike(right));
4967     // swap left and right
4968     // left < right <==> right > left <==> (right >= left + 1)
4969     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4970
4971     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4972       // MAXVALUE < right? always false
4973       if (performedLt) emitCLRC; else emitSETC;
4974       goto correct_result_in_carry;
4975     } // if
4976
4977     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4978     // that's we handled it above.
4979     lit++;
4980
4981     dummy = left;
4982     left = right;
4983     right = dummy;
4984
4985     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4986   } else if (isAOP_LIT(right)) {
4987     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4988   } // if
4989
4990   assert (isAOP_REGlike(left)); // left must be register or the like
4991   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4992
4993   /*************************************************
4994    * special cases go here                         *
4995    *************************************************/
4996
4997   if (isAOP_LIT(right)) {
4998     if (!sign) {
4999       // unsigned comparison to a literal
5000       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5001       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5002       #endif
5003       if (lit == 0) {
5004         // unsigned left < 0? always false
5005         if (performedLt) emitCLRC; else emitSETC;
5006         goto correct_result_in_carry;
5007       }
5008     } else {
5009       // signed comparison to a literal
5010       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5011       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5012       #endif
5013       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5014         // signed left < 0x80000000? always false
5015         if (performedLt) emitCLRC; else emitSETC;
5016         goto correct_result_in_carry;
5017       } else if (lit == 0) {
5018         // compare left < 0; set CARRY if SIGNBIT(left) is set
5019         if (performedLt) emitSETC; else emitCLRC;
5020         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5021         if (performedLt) emitCLRC; else emitSETC;
5022         goto correct_result_in_carry;
5023       }
5024     } // if (!sign)
5025   } // right is literal
5026
5027   /*************************************************
5028    * perform a general case comparison             *
5029    * make sure we get CARRY==1 <==> left >= right  *
5030    *************************************************/
5031   // compare most significant bytes
5032   //DEBUGpc ("comparing bytes at offset %d", size);
5033   if (!sign) {
5034     // unsigned comparison
5035     mov2w_regOrLit (AOP(right), lit, size);
5036     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5037   } else {
5038     // signed comparison
5039     // (add 2^n to both operands then perform an unsigned comparison)
5040     if (isAOP_LIT(right)) {
5041       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5042       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5043
5044       if (litbyte == 0x80) {
5045         // left >= 0x80 -- always true, but more bytes to come
5046         pic16_mov2w (AOP(left), size);
5047         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5048         emitSETC;
5049       } else {
5050         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5051         pic16_mov2w (AOP(left), size);
5052         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5053         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5054       } // if
5055     } else {
5056       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5057       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5058       pic16_mov2w (AOP(left), size);
5059       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5060       pic16_emitpcode (POC_MOVWF, pctemp);
5061       pic16_mov2w (AOP(right), size);
5062       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5063       pic16_emitpcode (POC_SUBFW, pctemp);
5064       //pic16_popReleaseTempReg(pctemp, 1);
5065     }
5066   } // if (!sign)
5067
5068   // compare remaining bytes (treat as unsigned case from above)
5069   templbl = newiTempLabel ( NULL );
5070   offs = size;
5071   while (offs--) {
5072     //DEBUGpc ("comparing bytes at offset %d", offs);
5073     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5074     mov2w_regOrLit (AOP(right), lit, offs);
5075     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5076   } // while (offs)
5077   pic16_emitpLabel (templbl->key);
5078   goto result_in_carry;
5079
5080 result_in_carry:
5081   
5082   /****************************************************
5083    * now CARRY contains the result of the comparison: *
5084    * SUBWF sets CARRY iff                             *
5085    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5086    * (F=left, W=right)
5087    ****************************************************/
5088
5089   if (performedLt) {
5090     if (result && AOP_TYPE(result) != AOP_CRY) {
5091       // value will be stored
5092       emitTOGC;
5093     } else {
5094       // value wil only be used in the following genSkipc()
5095       rIfx.condition ^= 1;
5096     }
5097   } // if
5098
5099 correct_result_in_carry:
5100
5101   // assign result to variable (if neccessary)
5102   if (result && AOP_TYPE(result) != AOP_CRY) {
5103     //DEBUGpc ("assign result");
5104     size = AOP_SIZE(result);
5105     while (size--) {
5106       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5107     } // while
5108     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5109   } // if (result)
5110
5111   // perform conditional jump
5112   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5113   if (ifx) {
5114     //DEBUGpc ("generate control flow");
5115     rIfx.condition ^= 1;
5116     genSkipc (&rIfx);
5117     ifx->generated = 1;
5118   } // if
5119 }
5120
5121 #elif 1
5122                 /* { */
5123       /* original code */
5124 static void genCmp (operand *left,operand *right,
5125                     operand *result, iCode *ifx, int sign)
5126 {
5127   int size; //, offset = 0 ;
5128   unsigned long lit = 0L,i = 0;
5129   resolvedIfx rFalseIfx;
5130   //  resolvedIfx rTrueIfx;
5131   symbol *truelbl;
5132   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5133 /*
5134   if(ifx) {
5135     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5136     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5137   }
5138 */
5139
5140   FENTRY;
5141   
5142   resolveIfx(&rFalseIfx,ifx);
5143   truelbl  = newiTempLabel(NULL);
5144   size = max(AOP_SIZE(left),AOP_SIZE(right));
5145
5146   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5147
5148 #define _swapp
5149
5150   /* if literal is on the right then swap with left */
5151   if ((AOP_TYPE(right) == AOP_LIT)) {
5152     operand *tmp = right ;
5153     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5154     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5155 #ifdef _swapp
5156
5157     lit = (lit - 1) & mask;
5158     right = left;
5159     left = tmp;
5160     rFalseIfx.condition ^= 1;
5161 #endif
5162
5163   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5164     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5165   }
5166
5167
5168   //if(IC_TRUE(ifx) == NULL)
5169   /* if left & right are bit variables */
5170   if (AOP_TYPE(left) == AOP_CRY &&
5171       AOP_TYPE(right) == AOP_CRY ) {
5172     assert (0 && "bit variables used in genCmp");
5173     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5174     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5175   } else {
5176     /* subtract right from left if at the
5177        end the carry flag is set then we know that
5178        left is greater than right */
5179
5180     symbol *lbl  = newiTempLabel(NULL);
5181
5182 #if 0
5183         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5184                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5185 #endif
5186
5187 #ifndef _swapp
5188     if(AOP_TYPE(right) == AOP_LIT) {
5189
5190       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5191
5192       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5193
5194       /* special cases */
5195
5196       if(lit == 0) {
5197
5198         if(sign != 0) 
5199           genSkipCond(&rFalseIfx,left,size-1,7);
5200         else 
5201           /* no need to compare to 0...*/
5202           /* NOTE: this is a de-generate compare that most certainly 
5203            *       creates some dead code. */
5204           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5205
5206         if(ifx) ifx->generated = 1;
5207         return;
5208
5209       }
5210       size--;
5211
5212       if(size == 0) {
5213         //i = (lit >> (size*8)) & 0xff;
5214         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5215         
5216         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5217
5218         i = ((0-lit) & 0xff);
5219         if(sign) {
5220           if( i == 0x81) { 
5221             /* lit is 0x7f, all signed chars are less than
5222              * this except for 0x7f itself */
5223             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5224             genSkipz2(&rFalseIfx,0);
5225           } else {
5226             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5227             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5228             genSkipc(&rFalseIfx);
5229           }
5230
5231         } else {
5232           if(lit == 1) {
5233             genSkipz2(&rFalseIfx,1);
5234           } else {
5235             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5236             genSkipc(&rFalseIfx);
5237           }
5238         }
5239
5240         if(ifx) ifx->generated = 1;
5241         return;
5242       }
5243
5244       /* chars are out of the way. now do ints and longs */
5245
5246
5247       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5248         
5249       /* special cases */
5250
5251       if(sign) {
5252
5253         if(lit == 0) {
5254           genSkipCond(&rFalseIfx,left,size,7);
5255           if(ifx) ifx->generated = 1;
5256           return;
5257         }
5258
5259         if(lit <0x100) {
5260           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5261
5262           //rFalseIfx.condition ^= 1;
5263           //genSkipCond(&rFalseIfx,left,size,7);
5264           //rFalseIfx.condition ^= 1;
5265
5266           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5267           if(rFalseIfx.condition)
5268             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5269           else
5270             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5271
5272           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5273           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5274           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5275
5276           while(size > 1)
5277             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5278
5279           if(rFalseIfx.condition) {
5280             emitSKPZ;
5281             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5282
5283           } else {
5284             emitSKPNZ;
5285           }
5286
5287           genSkipc(&rFalseIfx);
5288           pic16_emitpLabel(truelbl->key);
5289           if(ifx) ifx->generated = 1;
5290           return;
5291
5292         }
5293
5294         if(size == 1) {
5295
5296           if( (lit & 0xff) == 0) {
5297             /* lower byte is zero */
5298             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5299             i = ((lit >> 8) & 0xff) ^0x80;
5300             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5301             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5302             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5303             genSkipc(&rFalseIfx);
5304
5305
5306             if(ifx) ifx->generated = 1;
5307             return;
5308
5309           }
5310         } else {
5311           /* Special cases for signed longs */
5312           if( (lit & 0xffffff) == 0) {
5313             /* lower byte is zero */
5314             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5315             i = ((lit >> 8*3) & 0xff) ^0x80;
5316             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5317             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5318             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5319             genSkipc(&rFalseIfx);
5320
5321
5322             if(ifx) ifx->generated = 1;
5323             return;
5324
5325           }
5326
5327         }
5328
5329
5330         if(lit & (0x80 << (size*8))) {
5331           /* lit is negative */
5332           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5333
5334           //genSkipCond(&rFalseIfx,left,size,7);
5335
5336           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5337
5338           if(rFalseIfx.condition)
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5340           else
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5342
5343
5344         } else {
5345           /* lit is positive */
5346           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5347           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5348           if(rFalseIfx.condition)
5349             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5350           else
5351             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5352
5353         }
5354
5355         /*
5356           This works, but is only good for ints.
5357           It also requires a "known zero" register.
5358           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5359           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5360           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5361           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5362           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5363           genSkipc(&rFalseIfx);
5364
5365           pic16_emitpLabel(truelbl->key);
5366           if(ifx) ifx->generated = 1;
5367           return;
5368         **/
5369           
5370         /* There are no more special cases, so perform a general compare */
5371   
5372         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5373         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374
5375         while(size--) {
5376
5377           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5378           emitSKPNZ;
5379           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5380         }
5381         //rFalseIfx.condition ^= 1;
5382         genSkipc(&rFalseIfx);
5383
5384         pic16_emitpLabel(truelbl->key);
5385
5386         if(ifx) ifx->generated = 1;
5387         return;
5388
5389
5390       }
5391
5392
5393       /* sign is out of the way. So now do an unsigned compare */
5394       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5395
5396
5397       /* General case - compare to an unsigned literal on the right.*/
5398
5399       i = (lit >> (size*8)) & 0xff;
5400       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5401       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5402       while(size--) {
5403         i = (lit >> (size*8)) & 0xff;
5404
5405         if(i) {
5406           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5407           emitSKPNZ;
5408           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5409         } else {
5410           /* this byte of the lit is zero, 
5411            *if it's not the last then OR in the variable */
5412           if(size)
5413             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5414         }
5415       }
5416
5417
5418       pic16_emitpLabel(lbl->key);
5419 //      pic16_emitpLabel(truelbl->key);
5420       //if(emitFinalCheck)
5421       genSkipc(&rFalseIfx);
5422       if(sign)
5423         pic16_emitpLabel(truelbl->key);
5424
5425       if(ifx) ifx->generated = 1;
5426       return;
5427
5428
5429     }
5430 #endif  // _swapp
5431
5432     if(AOP_TYPE(left) == AOP_LIT) {
5433       //symbol *lbl = newiTempLabel(NULL);
5434
5435       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5436
5437
5438       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5439
5440       /* Special cases */
5441       if((lit == 0) && (sign == 0)){
5442
5443         size--;
5444         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5445         while(size) 
5446           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5447
5448         genSkipz2(&rFalseIfx,0);
5449         if(ifx) ifx->generated = 1;
5450         return;
5451       }
5452
5453       if(size==1) {
5454         /* Special cases */
5455         lit &= 0xff;
5456         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5457           /* degenerate compare can never be true */
5458           if(rFalseIfx.condition == 0)
5459             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5460
5461           if(ifx) ifx->generated = 1;
5462           return;
5463         }
5464
5465         if(sign) {
5466           /* signed comparisons to a literal byte */
5467
5468           int lp1 = (lit+1) & 0xff;
5469
5470           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5471           switch (lp1) {
5472           case 0:
5473             rFalseIfx.condition ^= 1;
5474             genSkipCond(&rFalseIfx,right,0,7);
5475             break;
5476           case 0x7f:
5477             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5478             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5479             genSkipz2(&rFalseIfx,1);
5480             break;
5481           default:
5482             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5483             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5484             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5485             rFalseIfx.condition ^= 1;
5486             genSkipc(&rFalseIfx);
5487             break;
5488           }
5489         } else {
5490           /* unsigned comparisons to a literal byte */
5491
5492           switch(lit & 0xff ) {
5493           case 0:
5494             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5495             genSkipz2(&rFalseIfx,0);
5496             break;
5497           case 0x7f:
5498             rFalseIfx.condition ^= 1;
5499             genSkipCond(&rFalseIfx,right,0,7);
5500             break;
5501
5502           default:
5503             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5504             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5505             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5506             rFalseIfx.condition ^= 1;
5507             if (AOP_TYPE(result) == AOP_CRY)
5508               genSkipc(&rFalseIfx);
5509             else {
5510               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5511               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5512             }         
5513             break;
5514           }
5515         }
5516
5517         if(ifx) ifx->generated = 1;
5518         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5519                 goto check_carry;
5520         return;
5521
5522       } else {
5523
5524         /* Size is greater than 1 */
5525
5526         if(sign) {
5527           int lp1 = lit+1;
5528
5529           size--;
5530
5531           if(lp1 == 0) {
5532             /* this means lit = 0xffffffff, or -1 */
5533
5534
5535             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5536             rFalseIfx.condition ^= 1;
5537             genSkipCond(&rFalseIfx,right,size,7);
5538             if(ifx) ifx->generated = 1;
5539
5540             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5541               goto check_carry;
5542
5543             return;
5544           }
5545
5546           if(lit == 0) {
5547             int s = size;
5548
5549             if(rFalseIfx.condition) {
5550               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5551               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5552             }
5553
5554             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5555             while(size--)
5556               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5557
5558
5559             emitSKPZ;
5560             if(rFalseIfx.condition) {
5561               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5562               pic16_emitpLabel(truelbl->key);
5563             }else {
5564               rFalseIfx.condition ^= 1;
5565               genSkipCond(&rFalseIfx,right,s,7);
5566             }
5567
5568             if(ifx) ifx->generated = 1;
5569
5570             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5571               goto check_carry;
5572
5573             return;
5574           }
5575
5576           if((size == 1) &&  (0 == (lp1&0xff))) {
5577             /* lower byte of signed word is zero */
5578             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5579             i = ((lp1 >> 8) & 0xff) ^0x80;
5580             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5581             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5582             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5583
5584             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5585               emitTOGC;
5586               if(ifx) ifx->generated = 1;
5587               goto check_carry;
5588             } else {
5589               rFalseIfx.condition ^= 1;
5590               genSkipc(&rFalseIfx);
5591               if(ifx) ifx->generated = 1;
5592             }
5593
5594             return;
5595           }
5596
5597           if(lit & (0x80 << (size*8))) {
5598             /* Lit is less than zero */
5599             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5600             //rFalseIfx.condition ^= 1;
5601             //genSkipCond(&rFalseIfx,left,size,7);
5602             //rFalseIfx.condition ^= 1;
5603             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5604             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5605
5606             if(rFalseIfx.condition)
5607               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5608             else
5609               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5610
5611
5612           } else {
5613             /* Lit is greater than or equal to zero */
5614             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5615             //rFalseIfx.condition ^= 1;
5616             //genSkipCond(&rFalseIfx,right,size,7);
5617             //rFalseIfx.condition ^= 1;
5618
5619             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5620             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5621
5622             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5623             if(rFalseIfx.condition)
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5625             else
5626               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5627
5628           }
5629
5630           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5631           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5632
5633           while(size--) {
5634
5635             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5636             emitSKPNZ;
5637             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5638           }
5639           rFalseIfx.condition ^= 1;
5640           //rFalseIfx.condition = 1;
5641           genSkipc(&rFalseIfx);
5642
5643           pic16_emitpLabel(truelbl->key);
5644
5645           if(ifx) ifx->generated = 1;
5646
5647
5648           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649             goto check_carry;
5650
5651           return;
5652           // end of if (sign)
5653         } else {
5654
5655           /* compare word or long to an unsigned literal on the right.*/
5656
5657
5658           size--;
5659           if(lit < 0xff) {
5660             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5661             switch (lit) {
5662             case 0:
5663               break; /* handled above */
5664 /*
5665             case 0xff:
5666               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5667               while(size--)
5668                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5669               genSkipz2(&rFalseIfx,0);
5670               break;
5671 */
5672             default:
5673               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5674               while(--size)
5675                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5676
5677               emitSKPZ;
5678               if(rFalseIfx.condition)
5679                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5680               else
5681                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5682
5683
5684               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5685               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5686
5687               rFalseIfx.condition ^= 1;
5688               genSkipc(&rFalseIfx);
5689             }
5690
5691             pic16_emitpLabel(truelbl->key);
5692
5693             if(ifx) ifx->generated = 1;
5694
5695             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5696               goto check_carry;
5697
5698             return;
5699           }
5700
5701
5702           lit++;
5703           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5704           i = (lit >> (size*8)) & 0xff;
5705
5706           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5707           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708
5709           while(size--) {
5710             i = (lit >> (size*8)) & 0xff;
5711
5712             if(i) {
5713               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5714               emitSKPNZ;
5715               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5716             } else {
5717               /* this byte of the lit is zero, 
5718                * if it's not the last then OR in the variable */
5719               if(size)
5720                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5721             }
5722           }
5723
5724
5725           pic16_emitpLabel(lbl->key);
5726
5727           rFalseIfx.condition ^= 1;
5728
5729           genSkipc(&rFalseIfx);
5730         }
5731
5732         if(sign)
5733           pic16_emitpLabel(truelbl->key);
5734         if(ifx) ifx->generated = 1;
5735
5736             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5737               goto check_carry;
5738
5739         return;
5740       }
5741     }
5742     /* Compare two variables */
5743
5744     DEBUGpic16_emitcode(";sign","%d",sign);
5745
5746     size--;
5747     if(sign) {
5748       /* Sigh. thus sucks... */
5749       if(size) {
5750         pCodeOp *pctemp;
5751         
5752         pctemp = pic16_popGetTempReg(1);
5753         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5754         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5755         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5756         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5757         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5758         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759         pic16_popReleaseTempReg(pctemp, 1);
5760       } else {
5761         /* Signed char comparison */
5762         /* Special thanks to Nikolai Golovchenko for this snippet */
5763         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5764         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5765         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5766         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5767         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5768         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5769
5770         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5771         genSkipc(&rFalseIfx);
5772           
5773         if(ifx) ifx->generated = 1;
5774
5775             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776               goto check_carry;
5777
5778         return;
5779       }
5780
5781     } else {
5782
5783       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5784       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5785     }
5786
5787
5788     /* The rest of the bytes of a multi-byte compare */
5789     while (size) {
5790
5791       emitSKPZ;
5792       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5793       size--;
5794
5795       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5796       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5797
5798
5799     }
5800
5801     pic16_emitpLabel(lbl->key);
5802
5803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5804     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5805         (AOP_TYPE(result) == AOP_REG)) {
5806       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5807       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5808     } else {
5809       genSkipc(&rFalseIfx);
5810     }         
5811     //genSkipc(&rFalseIfx);
5812     if(ifx) ifx->generated = 1;
5813
5814
5815             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5816               goto check_carry;
5817
5818     return;
5819
5820   }
5821
5822 check_carry:
5823   if ((AOP_TYPE(result) != AOP_CRY) 
5824         && AOP_SIZE(result)) {
5825     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5826
5827     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5828
5829     pic16_outBitC(result);
5830   } else {
5831     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5832     /* if the result is used in the next
5833        ifx conditional branch then generate
5834        code a little differently */
5835     if (ifx )
5836       genIfxJump (ifx,"c");
5837     else
5838       pic16_outBitC(result);
5839     /* leave the result in acc */
5840   }
5841
5842 }
5843
5844 #else   /* old version of genCmp() */   /* } else { */
5845
5846 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5847 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5848         operand *result, int offset, int invert_op)
5849 {
5850   /* add code here */
5851   
5852   /* check condition, > or < ?? */
5853   if(rIfx->condition != 0)invert_op ^= 1;
5854   
5855   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5856
5857   if(!ifx)invert_op ^= 1;
5858
5859   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5860       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5861   
5862   /* do selection */
5863   if(!invert_op)return POC_CPFSGT;
5864   else return POC_CPFSLT;
5865 }
5866
5867 static int compareAopfirstpass=1;
5868
5869 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5870             operand *oper, int offset, operand *result,
5871             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5872             symbol *tlbl)
5873 {
5874   int op;
5875   symbol *truelbl;
5876
5877   /* invert if there is a result to be loaded, in order to fit,
5878    * SETC/CLRC sequence */
5879   if(AOP_SIZE(result))invert_op ^= 1;
5880
5881 //  if(sign && !offset)invert_op ^= 1;
5882   
5883 //  if(sign)invert_op ^= 1;
5884   
5885   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5886
5887   if(AOP_SIZE(result) && compareAopfirstpass) {
5888     if(!ifx) {
5889       if(pcop2)
5890         pic16_emitpcode(POC_SETF, pcop2);
5891       else
5892         emitSETC;
5893     } else {
5894       if(pcop2)
5895         pic16_emitpcode(POC_CLRF, pcop2);
5896       else
5897         emitCLRC;
5898     }
5899   }
5900
5901   compareAopfirstpass = 0;
5902
5903       /* there is a bug when comparing operands with size > 1,
5904        * because higher bytes can be equal and test should be performed
5905        * to the next lower byte, current algorithm, considers operands
5906        * inequal in these cases! -- VR 20041107 */
5907
5908     
5909   if(pcop)
5910     pic16_emitpcode(op, pcop);
5911   else
5912     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5913
5914
5915   if((!sign || !offset) && AOP_SIZE(result)) {
5916     if(!ifx) {
5917       if(pcop2)
5918         pic16_emitpcode(POC_CLRF, pcop2);
5919         else
5920         emitCLRC;
5921     } else {
5922       if(pcop2)
5923         pic16_emitpcode(POC_SETF, pcop2);
5924       else
5925         emitSETC;
5926     }
5927     
5928     /* don't emit final branch (offset == 0) */
5929     if(offset) {
5930
5931       if(pcop2)
5932         pic16_emitpcode(POC_RRCF, pcop2);
5933
5934       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5935     }
5936   } else {
5937     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5938       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5939             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5940
5941       truelbl = newiTempLabel( NULL );
5942       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5943       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5944         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5945       else
5946         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5947       pic16_emitpLabel(truelbl->key);
5948     } else {
5949       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5950     }
5951   }
5952 }
5953
5954
5955   
5956
5957 #if 1   /* { */
5958 static void genCmp (operand *left, operand *right,
5959                     operand *result, iCode *ifx, int sign)
5960 {
5961   int size, cmpop=1;
5962   long lit = 0L;
5963   resolvedIfx rFalseIfx;
5964   symbol *falselbl, *tlbl;
5965
5966     FENTRY;
5967     
5968     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5969
5970     resolveIfx(&rFalseIfx, ifx);
5971     size = max(AOP_SIZE(left), AOP_SIZE(right));
5972     
5973     /* if left & right are bit variables */
5974     if(AOP_TYPE(left) == AOP_CRY
5975       && AOP_TYPE(right) == AOP_CRY ) {
5976
5977         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5978         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5979         
5980         werror(W_POSSBUG2, __FILE__, __LINE__);
5981         exit(-1);
5982     }
5983     
5984     /* if literal is on the right then swap with left */
5985     if((AOP_TYPE(right) == AOP_LIT)) {
5986       operand *tmp = right ;
5987 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5988
5989         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5990
5991 //      lit = (lit - 1) & mask;
5992         right = left;
5993         left = tmp;
5994         rFalseIfx.condition ^= 1;               /* reverse compare */
5995     } else
5996     if ((AOP_TYPE(left) == AOP_LIT)) {
5997       /* float compares are handled by support functions */
5998       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5999     }
6000
6001     /* actual comparing algorithm */
6002 //    size = AOP_SIZE( right );
6003
6004     falselbl = newiTempLabel( NULL );
6005     if(AOP_TYPE(left) == AOP_LIT) {
6006       /* compare to literal */
6007       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6008       
6009       if(sign) {
6010         pCodeOp *pct, *pct2;
6011         symbol *tlbl1;
6012
6013         /* signed compare */
6014         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6015
6016         pct = pic16_popCopyReg(&pic16_pc_prodl);
6017         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6018         tlbl = newiTempLabel( NULL );
6019         
6020         /* first compare signs:
6021          *  a. if both are positive, compare just like unsigned
6022          *  b. if both are negative, invert cmpop, compare just like unsigned
6023          *  c. if different signs, determine the result directly */
6024
6025         size--;
6026
6027 #if 1
6028         /* { */
6029         tlbl1 = newiTempLabel( NULL );
6030 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6031
6032         if(lit > 0) {
6033
6034           /* literal is zero or positive:
6035            *  a. if carry is zero, too, continue compare,
6036            *  b. if carry is set, then continue depending on cmpop ^ condition:
6037            *    1. '<' return false (literal < variable),
6038            *    2. '>' return true (literal > variable) */
6039 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6040           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6041           
6042           
6043           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6044           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6045         } else 
6046         if(lit < 0) {
6047           
6048           /* literal is negative:
6049            *  a. if carry is set, too, continue compare,
6050            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6051            *    1. '<' return true (literal < variable),
6052            *    2. '>' return false (literal > variable) */
6053 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6054           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6055           
6056           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6057           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6058         }
6059 #if 1
6060         else {
6061           /* lit == 0 */
6062           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6063           
6064           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6065           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6066         }
6067 #endif
6068         
6069         
6070         pic16_emitpLabel( tlbl1->key );
6071 #endif  /* } */
6072
6073         compareAopfirstpass=1;
6074 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6075 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6076 //        pic16_emitpcode(POC_MOVWF, pct);
6077
6078 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6079         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6080 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6081         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6082
6083         /* generic case */        
6084           while( size-- ) {
6085 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6086 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6087 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6088 //            pic16_emitpcode(POC_MOVWF, pct);
6089
6090 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6091             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6092             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6093 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6094 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6095           }
6096 //        }
6097         
6098         if(ifx)ifx->generated = 1;
6099
6100         if(AOP_SIZE(result)) {
6101           pic16_emitpLabel(tlbl->key);
6102           pic16_emitpLabel(falselbl->key);
6103           pic16_outBitOp( result, pct2 );
6104         } else {
6105           pic16_emitpLabel(tlbl->key);
6106         }
6107       } else {
6108
6109
6110         /* unsigned compare */      
6111         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6112     
6113         compareAopfirstpass=1;
6114         while(size--) {
6115           
6116           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6117           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6118
6119         }
6120
6121         if(ifx)ifx->generated = 1;
6122
6123
6124         if(AOP_SIZE(result)) {
6125           pic16_emitpLabel(falselbl->key);
6126           pic16_outBitC( result );
6127         }
6128
6129       }
6130     } else {
6131       /* compare registers */
6132       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6133
6134
6135       if(sign) {
6136         pCodeOp *pct, *pct2;
6137         
6138         /* signed compare */
6139         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6140
6141         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6142         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6143         tlbl = newiTempLabel( NULL );
6144         
6145         compareAopfirstpass=1;
6146
6147         size--;
6148         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6149 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6150         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6151         pic16_emitpcode(POC_MOVWF, pct);
6152
6153         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6154 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6155         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6156
6157         /* WREG already holds left + 0x80 */
6158         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159         
6160         while( size-- ) {
6161           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6162 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6163           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6164           pic16_emitpcode(POC_MOVWF, pct);
6165                 
6166           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6167 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6168           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6169
6170           /* WREG already holds left + 0x80 */
6171           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6172 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6173         }
6174         
6175         if(ifx)ifx->generated = 1;
6176
6177         if(AOP_SIZE(result)) {
6178           pic16_emitpLabel(tlbl->key);
6179           pic16_emitpLabel(falselbl->key);
6180           pic16_outBitOp( result, pct2 );
6181         } else {
6182           pic16_emitpLabel(tlbl->key);
6183         }
6184
6185       } else {
6186         /* unsigned compare */      
6187         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6188
6189         compareAopfirstpass=1;
6190         while(size--) {
6191           
6192           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6193           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6194
6195         }
6196
6197         if(ifx)ifx->generated = 1;
6198         if(AOP_SIZE(result)) {
6199
6200           pic16_emitpLabel(falselbl->key);
6201           pic16_outBitC( result );
6202         }
6203
6204       }
6205     }
6206 }
6207
6208 #else    /* } else { */
6209
6210 /* new version of genCmp -- VR 20041012 */
6211 static void genCmp (operand *left,operand *right,
6212                     operand *result, iCode *ifx, int sign)
6213 {
6214   int size; //, offset = 0 ;
6215   unsigned long lit = 0L,i = 0;
6216   resolvedIfx rFalseIfx;
6217   int willCheckCarry=0;
6218   //  resolvedIfx rTrueIfx;
6219   symbol *truelbl;
6220
6221     FENTRY;
6222   
6223   /* General concept:
6224    * subtract right from left if at the end the carry flag is set then we
6225    * know that left is greater than right */
6226             
6227   resolveIfx(&rFalseIfx,ifx);
6228   truelbl  = newiTempLabel(NULL);
6229   size = max(AOP_SIZE(left),AOP_SIZE(right));
6230
6231   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6232
6233   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6234    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6235   
6236
6237   /* if literal is on the right then swap with left */
6238   if ((AOP_TYPE(right) == AOP_LIT)) {
6239     operand *tmp = right ;
6240     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6241
6242       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6243
6244 //      lit = (lit - 1) & mask;
6245       right = left;
6246       left = tmp;
6247       rFalseIfx.condition ^= 1;         /* reverse compare */
6248   } else
6249   if ((AOP_TYPE(left) == AOP_LIT)) {
6250     /* float compares are handled by support functions */
6251     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6252   }
6253
6254
6255   //if(IC_TRUE(ifx) == NULL)
6256   /* if left & right are bit variables */
6257   if (AOP_TYPE(left) == AOP_CRY &&
6258       AOP_TYPE(right) == AOP_CRY ) {
6259
6260     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6261     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6262
6263   } else {
6264     symbol *lbl  = newiTempLabel(NULL);
6265
6266     if(AOP_TYPE(left) == AOP_LIT) {
6267       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6268
6269       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6270         willCheckCarry = 1;
6271       else willCheckCarry = 0;
6272
6273       /* Special cases */
6274       if((lit == 0) && (sign == 0)) {
6275         /* unsigned compare to 0 */
6276         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6277         
6278         size--;
6279         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6280         while(size) 
6281           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6282
6283         genSkipz2(&rFalseIfx,0);
6284         if(ifx)ifx->generated = 1;
6285         return;
6286       }
6287
6288       if(size==1) {
6289         /* Special cases */
6290         lit &= 0xff;
6291         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6292           /* degenerate compare can never be true */
6293           if(rFalseIfx.condition == 0)
6294             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6295
6296           if(ifx) ifx->generated = 1;
6297           return;
6298         }
6299
6300         if(sign) {
6301           /* signed comparisons to a literal byte */
6302           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6303
6304           int lp1 = (lit+1) & 0xff;
6305
6306           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6307           switch (lp1) {
6308           case 0:
6309             rFalseIfx.condition ^= 1;
6310             genSkipCond(&rFalseIfx,right,0,7);
6311             break;
6312           case 0x7f:
6313             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6314             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6315             genSkipz2(&rFalseIfx,1);
6316             break;
6317           default:
6318             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6319             
6320             if(rFalseIfx.condition)
6321               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6322             else
6323               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6324
6325             if(willCheckCarry) {
6326               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6327               else { emitSETC; emitCLRC; }
6328               
6329             } else {
6330               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6331             }              
6332                       
6333 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6334             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6335             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6336             rFalseIfx.condition ^= 1;
6337             genSkipc(&rFalseIfx);
6338 */
6339             break;
6340           }
6341         } else {
6342           /* unsigned comparisons to a literal byte */
6343           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6344
6345           switch(lit & 0xff ) {
6346                           /* special cases */
6347           case 0:
6348             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6349             genSkipz2(&rFalseIfx,0);
6350             break;
6351           case 0x7f:
6352             rFalseIfx.condition ^= 1;
6353             genSkipCond(&rFalseIfx,right,0,7);
6354             break;
6355           default:
6356             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6357             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6358             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6359             rFalseIfx.condition ^= 1;
6360             if (AOP_TYPE(result) == AOP_CRY)
6361               genSkipc(&rFalseIfx);
6362             else {
6363               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6364               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6365             }         
6366             break;
6367           }
6368         }
6369
6370         if(ifx) ifx->generated = 1;
6371         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6372                 goto check_carry;
6373         return;
6374
6375       } else {
6376
6377         /* Size is greater than 1 */
6378
6379         if(sign) {
6380           int lp1 = lit+1;
6381
6382           size--;
6383
6384           if(lp1 == 0) {
6385             /* this means lit = 0xffffffff, or -1 */
6386
6387
6388             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6389             rFalseIfx.condition ^= 1;
6390             genSkipCond(&rFalseIfx,right,size,7);
6391             if(ifx) ifx->generated = 1;
6392             return;
6393           }
6394
6395           if(lit == 0) {
6396             int s = size;
6397
6398             if(rFalseIfx.condition) {
6399               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6400               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6401             }
6402
6403             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6404             while(size--)
6405               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6406
6407
6408             emitSKPZ;
6409             if(rFalseIfx.condition) {
6410               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6411               pic16_emitpLabel(truelbl->key);
6412             }else {
6413               rFalseIfx.condition ^= 1;
6414               genSkipCond(&rFalseIfx,right,s,7);
6415             }
6416
6417             if(ifx) ifx->generated = 1;
6418             return;
6419           }
6420
6421           if((size == 1) &&  (0 == (lp1&0xff))) {
6422             /* lower byte of signed word is zero */
6423             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6424             i = ((lp1 >> 8) & 0xff) ^0x80;
6425             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6426             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6427             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6428             rFalseIfx.condition ^= 1;
6429             genSkipc(&rFalseIfx);
6430
6431
6432             if(ifx) ifx->generated = 1;
6433             return;
6434           }
6435
6436           if(lit & (0x80 << (size*8))) {
6437             /* Lit is less than zero */
6438             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6439             //rFalseIfx.condition ^= 1;
6440             //genSkipCond(&rFalseIfx,left,size,7);
6441             //rFalseIfx.condition ^= 1;
6442             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6443             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6444
6445             if(rFalseIfx.condition)
6446               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6447             else
6448               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6449
6450
6451           } else {
6452             /* Lit is greater than or equal to zero */
6453             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6454             //rFalseIfx.condition ^= 1;
6455             //genSkipCond(&rFalseIfx,right,size,7);
6456             //rFalseIfx.condition ^= 1;
6457
6458             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6459             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6460
6461             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6462             if(rFalseIfx.condition)
6463               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6464             else
6465               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6466
6467           }
6468
6469
6470           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6471           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6472
6473           while(size--) {
6474
6475             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6476             emitSKPNZ;
6477             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6478           }
6479           rFalseIfx.condition ^= 1;
6480           //rFalseIfx.condition = 1;
6481           genSkipc(&rFalseIfx);
6482
6483           pic16_emitpLabel(truelbl->key);
6484
6485           if(ifx) ifx->generated = 1;
6486           return;
6487           // end of if (sign)
6488         } else {
6489
6490           /* compare word or long to an unsigned literal on the right.*/
6491
6492
6493           size--;
6494           if(lit < 0xff) {
6495             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6496             switch (lit) {
6497             case 0:
6498               break; /* handled above */
6499 /*
6500             case 0xff:
6501               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6502               while(size--)
6503                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6504               genSkipz2(&rFalseIfx,0);
6505               break;
6506 */
6507             default:
6508               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6509               while(--size)
6510                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6511
6512               emitSKPZ;
6513               if(rFalseIfx.condition)
6514                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6515               else
6516                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6517
6518
6519               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6520               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6521
6522               rFalseIfx.condition ^= 1;
6523               genSkipc(&rFalseIfx);
6524             }
6525
6526             pic16_emitpLabel(truelbl->key);
6527
6528             if(ifx) ifx->generated = 1;
6529             return;
6530           }
6531
6532
6533           lit++;
6534           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6535           i = (lit >> (size*8)) & 0xff;
6536
6537           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6538           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6539
6540           while(size--) {
6541             i = (lit >> (size*8)) & 0xff;
6542
6543             if(i) {
6544               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6545               emitSKPNZ;
6546               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6547             } else {
6548               /* this byte of the lit is zero, 
6549                * if it's not the last then OR in the variable */
6550               if(size)
6551                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6552             }
6553           }
6554
6555
6556           pic16_emitpLabel(lbl->key);
6557
6558           rFalseIfx.condition ^= 1;
6559
6560           genSkipc(&rFalseIfx);
6561         }
6562
6563         if(sign)
6564           pic16_emitpLabel(truelbl->key);
6565         if(ifx) ifx->generated = 1;
6566         return;
6567       }
6568     }
6569     /* Compare two variables */
6570
6571     DEBUGpic16_emitcode(";sign","%d",sign);
6572
6573     size--;
6574     if(sign) {
6575       /* Sigh. thus sucks... */
6576       if(size) {
6577         pCodeOp *pctemp;
6578         
6579         pctemp = pic16_popGetTempReg(1);
6580         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6581         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6582         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6583         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6584         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6585         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586         pic16_popReleaseTempReg(pctemp, 1);
6587       } else {
6588         /* Signed char comparison */
6589         /* Special thanks to Nikolai Golovchenko for this snippet */
6590         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6591         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6592         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6593         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6594         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6595         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6596
6597         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6598         genSkipc(&rFalseIfx);
6599           
6600         if(ifx) ifx->generated = 1;
6601         return;
6602       }
6603
6604     } else {
6605
6606       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6607       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6608     }
6609
6610
6611     /* The rest of the bytes of a multi-byte compare */
6612     while (size) {
6613
6614       emitSKPZ;
6615       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6616       size--;
6617
6618       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6619       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6620
6621
6622     }
6623
6624     pic16_emitpLabel(lbl->key);
6625
6626     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6627     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6628         (AOP_TYPE(result) == AOP_REG)) {
6629       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6630       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6631     } else {
6632       genSkipc(&rFalseIfx);
6633     }         
6634     //genSkipc(&rFalseIfx);
6635     if(ifx) ifx->generated = 1;
6636
6637     return;
6638
6639   }
6640
6641 check_carry:
6642   if ((AOP_TYPE(result) != AOP_CRY) 
6643         && AOP_SIZE(result)) {
6644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6645
6646     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6647
6648     pic16_outBitC(result);
6649   } else {
6650     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6651     /* if the result is used in the next
6652        ifx conditional branch then generate
6653        code a little differently */
6654     if (ifx )
6655       genIfxJump (ifx,"c");
6656     else
6657       pic16_outBitC(result);
6658     /* leave the result in acc */
6659   }
6660
6661 }
6662 #endif  /* } */
6663
6664
6665 #endif  /* } */
6666
6667
6668
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpGt :- greater than comparison                             */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpGt (iCode *ic, iCode *ifx)
6673 {
6674   operand *left, *right, *result;
6675   sym_link *letype , *retype;
6676   int sign ;
6677
6678     FENTRY;
6679     
6680     left = IC_LEFT(ic);
6681     right= IC_RIGHT(ic);
6682     result = IC_RESULT(ic);
6683
6684     letype = getSpec(operandType(left));
6685     retype =getSpec(operandType(right));
6686     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6687     /* assign the amsops */
6688     pic16_aopOp (left,ic,FALSE);
6689     pic16_aopOp (right,ic,FALSE);
6690     pic16_aopOp (result,ic,TRUE);
6691
6692     genCmp(right, left, result, ifx, sign);
6693
6694     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6695     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6696     pic16_freeAsmop(result,NULL,ic,TRUE); 
6697 }
6698
6699 /*-----------------------------------------------------------------*/
6700 /* genCmpLt - less than comparisons                                */
6701 /*-----------------------------------------------------------------*/
6702 static void genCmpLt (iCode *ic, iCode *ifx)
6703 {
6704   operand *left, *right, *result;
6705   sym_link *letype , *retype;
6706   int sign ;
6707
6708     FENTRY;
6709
6710     left = IC_LEFT(ic);
6711     right= IC_RIGHT(ic);
6712     result = IC_RESULT(ic);
6713
6714     letype = getSpec(operandType(left));
6715     retype =getSpec(operandType(right));
6716     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6717
6718     /* assign the amsops */
6719     pic16_aopOp (left,ic,FALSE);
6720     pic16_aopOp (right,ic,FALSE);
6721     pic16_aopOp (result,ic,TRUE);
6722
6723     genCmp(left, right, result, ifx, sign);
6724
6725     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6726     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6727     pic16_freeAsmop(result,NULL,ic,TRUE); 
6728 }
6729
6730 #if 0
6731 // not needed ATM
6732 // FIXME reenable literal optimisation when the pic16 port is stable
6733
6734 /*-----------------------------------------------------------------*/
6735 /* genc16bit2lit - compare a 16 bit value to a literal             */
6736 /*-----------------------------------------------------------------*/
6737 static void genc16bit2lit(operand *op, int lit, int offset)
6738 {
6739   int i;
6740
6741   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6742   if( (lit&0xff) == 0) 
6743     i=1;
6744   else
6745     i=0;
6746
6747   switch( BYTEofLONG(lit,i)) { 
6748   case 0:
6749     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6750     break;
6751   case 1:
6752     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6753     break;
6754   case 0xff:
6755     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6756     break;
6757   default:
6758     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6759     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6760   }
6761
6762   i ^= 1;
6763
6764   switch( BYTEofLONG(lit,i)) { 
6765   case 0:
6766     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6767     break;
6768   case 1:
6769     emitSKPNZ;
6770     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6771     break;
6772   case 0xff:
6773     emitSKPNZ;
6774     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6775     break;
6776   default:
6777     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6778     emitSKPNZ;
6779     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6780
6781   }
6782
6783 }
6784 #endif
6785
6786 #if 0
6787 // not needed ATM
6788 /*-----------------------------------------------------------------*/
6789 /* gencjneshort - compare and jump if not equal                    */
6790 /*-----------------------------------------------------------------*/
6791 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6792 {
6793   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6794   int offset = 0;
6795   int res_offset = 0;  /* the result may be a different size then left or right */
6796   int res_size = AOP_SIZE(result);
6797   resolvedIfx rIfx;
6798   symbol *lbl, *lbl_done;
6799
6800   unsigned long lit = 0L;
6801   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6802
6803   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6804   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6805   if(result)
6806     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6807   resolveIfx(&rIfx,ifx);
6808   lbl =  newiTempLabel(NULL);
6809   lbl_done =  newiTempLabel(NULL);
6810
6811
6812   /* if the left side is a literal or 
6813      if the right is in a pointer register and left 
6814      is not */
6815   if ((AOP_TYPE(left) == AOP_LIT) || 
6816       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6817     operand *t = right;
6818     right = left;
6819     left = t;
6820   }
6821   if(AOP_TYPE(right) == AOP_LIT)
6822     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6823
6824   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6825     preserve_result = 1;
6826
6827   if(result && !preserve_result)
6828     {
6829       int i;
6830       for(i = 0; i < AOP_SIZE(result); i++)
6831         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6832     }
6833
6834
6835   /* if the right side is a literal then anything goes */
6836   if (AOP_TYPE(right) == AOP_LIT &&
6837       AOP_TYPE(left) != AOP_DIR ) {
6838     switch(size) {
6839     case 2:
6840       genc16bit2lit(left, lit, 0);
6841       emitSKPZ;
6842       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6843       break;
6844     default:
6845       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6846       while (size--) {
6847         if(lit & 0xff) {
6848           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6849           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6850         } else {
6851           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6852         }
6853
6854         emitSKPZ;
6855         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6856         offset++;
6857         if(res_offset < res_size-1)
6858           res_offset++;
6859         lit >>= 8;
6860       }
6861       break;
6862     }
6863   }
6864
6865   /* if the right side is in a register or in direct space or
6866      if the left is a pointer register & right is not */    
6867   else if (AOP_TYPE(right) == AOP_REG ||
6868            AOP_TYPE(right) == AOP_DIR || 
6869            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6870            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6871     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6872     int lbl_key = lbl->key;
6873
6874     if(result) {
6875       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6876       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6877     }else {
6878       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6879       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6880               __FUNCTION__,__LINE__);
6881       return;
6882     }
6883    
6884 /*     switch(size) { */
6885 /*     case 2: */
6886 /*       genc16bit2lit(left, lit, 0); */
6887 /*       emitSKPNZ; */
6888 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6889 /*       break; */
6890 /*     default: */
6891     while (size--) {
6892       int emit_skip=1;
6893       if((AOP_TYPE(left) == AOP_DIR) && 
6894          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6895
6896         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6897         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6898
6899       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6900             
6901         switch (lit & 0xff) {
6902         case 0:
6903           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6904           break;
6905         case 1:
6906           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6907           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6908           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6909           emit_skip=0;
6910           break;
6911         case 0xff:
6912           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6913           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6914           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6915           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6916           emit_skip=0;
6917           break;
6918         default:
6919           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6920           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6921         }
6922         lit >>= 8;
6923
6924       } else {
6925         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6926       }
6927       if(emit_skip) {
6928         if(AOP_TYPE(result) == AOP_CRY) {
6929           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6930           if(rIfx.condition)
6931             emitSKPNZ;
6932           else
6933             emitSKPZ;
6934           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6935         } else {
6936           /* fix me. probably need to check result size too */
6937           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6938           if(rIfx.condition)
6939             emitSKPZ;
6940           else
6941             emitSKPNZ;
6942           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6943           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6944         }
6945         if(ifx)
6946           ifx->generated=1;
6947       }
6948       emit_skip++;
6949       offset++;
6950       if(res_offset < res_size-1)
6951         res_offset++;
6952     }
6953 /*       break; */
6954 /*     } */
6955   } else if(AOP_TYPE(right) == AOP_REG &&
6956             AOP_TYPE(left) != AOP_DIR){
6957
6958     while(size--) {
6959       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6960       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6961       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6962       if(rIfx.condition)
6963         emitSKPNZ;
6964       else
6965         emitSKPZ;
6966       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6967       offset++;
6968       if(res_offset < res_size-1)
6969         res_offset++;
6970     }
6971       
6972   }else{
6973     /* right is a pointer reg need both a & b */
6974     while(size--) {
6975       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6976       if(strcmp(l,"b"))
6977         pic16_emitcode("mov","b,%s",l);
6978       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6979       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6980       offset++;
6981     }
6982   }
6983
6984   if(result && preserve_result)
6985     {
6986       int i;
6987       for(i = 0; i < AOP_SIZE(result); i++)
6988         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6989     }
6990
6991   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6992
6993   if(result && preserve_result)
6994     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6995
6996   if(!rIfx.condition)
6997     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6998
6999   pic16_emitpLabel(lbl->key);
7000
7001   if(result && preserve_result)
7002     {
7003       int i;
7004       for(i = 0; i < AOP_SIZE(result); i++)
7005         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7006
7007       pic16_emitpLabel(lbl_done->key);
7008    }
7009
7010   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7011
7012   if(ifx)
7013     ifx->generated = 1;
7014 }
7015 #endif
7016
7017 #if 0
7018 /*-----------------------------------------------------------------*/
7019 /* gencjne - compare and jump if not equal                         */
7020 /*-----------------------------------------------------------------*/
7021 static void gencjne(operand *left, operand *right, iCode *ifx)
7022 {
7023     symbol *tlbl  = newiTempLabel(NULL);
7024
7025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7026     gencjneshort(left, right, lbl);
7027
7028     pic16_emitcode("mov","a,%s",one);
7029     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7030     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7031     pic16_emitcode("clr","a");
7032     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7033
7034     pic16_emitpLabel(lbl->key);
7035     pic16_emitpLabel(tlbl->key);
7036
7037 }
7038 #endif
7039
7040
7041 /*-----------------------------------------------------------------*/
7042 /* is_LitOp - check if operand has to be treated as literal        */
7043 /*-----------------------------------------------------------------*/
7044 static bool is_LitOp(operand *op)
7045 {
7046   return ((AOP_TYPE(op) == AOP_LIT)
7047       || ( (AOP_TYPE(op) == AOP_PCODE)
7048           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7049               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7050 }
7051
7052 /*-----------------------------------------------------------------*/
7053 /* is_LitAOp - check if operand has to be treated as literal        */
7054 /*-----------------------------------------------------------------*/
7055 static bool is_LitAOp(asmop *aop)
7056 {
7057   return ((aop->type == AOP_LIT)
7058       || ( (aop->type == AOP_PCODE)
7059           && ( (aop->aopu.pcop->type == PO_LITERAL)
7060               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7061 }
7062
7063
7064
7065 /*-----------------------------------------------------------------*/
7066 /* genCmpEq - generates code for equal to                          */
7067 /*-----------------------------------------------------------------*/
7068 static void genCmpEq (iCode *ic, iCode *ifx)
7069 {
7070   operand *left, *right, *result;
7071   symbol *falselbl = newiTempLabel(NULL);
7072   symbol *donelbl = newiTempLabel(NULL);
7073
7074   int preserve_result = 0;
7075   int generate_result = 0;
7076   int i=0;
7077
7078   FENTRY;
7079   
7080   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7081   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7082   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7083  
7084   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7085
7086   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7087     {
7088       werror(W_POSSBUG2, __FILE__, __LINE__);
7089       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7090       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7091       goto release;
7092     }
7093
7094   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7095     {
7096       operand *tmp = right ;
7097       right = left;
7098       left = tmp;
7099     }
7100
7101   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7102     preserve_result = 1;
7103
7104   if(result && AOP_SIZE(result))
7105     generate_result = 1;
7106
7107   if(generate_result && !preserve_result)
7108     {
7109       for(i = 0; i < AOP_SIZE(result); i++)
7110         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7111     }
7112
7113   for(i=0; i < AOP_SIZE(left); i++)
7114     {
7115       if(AOP_TYPE(left) != AOP_ACC)
7116         {
7117           if(is_LitOp(left))
7118             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7119           else
7120             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7121         }
7122       if(is_LitOp(right))
7123         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7124       else
7125         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7126
7127       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7128     }
7129
7130   // result == true
7131
7132   if(generate_result && preserve_result)
7133     {
7134       for(i = 0; i < AOP_SIZE(result); i++)
7135         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7136     }
7137
7138   if(generate_result)
7139     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7140
7141   if(generate_result && preserve_result)
7142     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7143
7144   if(ifx && IC_TRUE(ifx))
7145     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7146
7147   if(ifx && IC_FALSE(ifx))
7148     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7149
7150   pic16_emitpLabel(falselbl->key);
7151
7152   // result == false
7153
7154   if(ifx && IC_FALSE(ifx))
7155     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7156
7157   if(generate_result && preserve_result)
7158     {
7159       for(i = 0; i < AOP_SIZE(result); i++)
7160         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7161     }
7162
7163   pic16_emitpLabel(donelbl->key);
7164
7165   if(ifx)
7166     ifx->generated = 1;
7167
7168 release:
7169   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7170   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7171   pic16_freeAsmop(result,NULL,ic,TRUE);
7172
7173 }
7174
7175
7176 #if 0
7177 // old version kept for reference
7178
7179 /*-----------------------------------------------------------------*/
7180 /* genCmpEq - generates code for equal to                          */
7181 /*-----------------------------------------------------------------*/
7182 static void genCmpEq (iCode *ic, iCode *ifx)
7183 {
7184     operand *left, *right, *result;
7185     unsigned long lit = 0L;
7186     int size,offset=0;
7187     symbol *falselbl  = newiTempLabel(NULL);
7188
7189
7190     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7191
7192     if(ifx)
7193       DEBUGpic16_emitcode ("; ifx is non-null","");
7194     else
7195       DEBUGpic16_emitcode ("; ifx is null","");
7196
7197     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7198     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7199     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7200
7201     size = max(AOP_SIZE(left),AOP_SIZE(right));
7202
7203     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7204
7205     /* if literal, literal on the right or 
7206     if the right is in a pointer register and left 
7207     is not */
7208     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7209         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7210       operand *tmp = right ;
7211       right = left;
7212       left = tmp;
7213     }
7214
7215
7216     if(ifx && !AOP_SIZE(result)){
7217         symbol *tlbl;
7218         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7219         /* if they are both bit variables */
7220         if (AOP_TYPE(left) == AOP_CRY &&
7221             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7222                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7223             if(AOP_TYPE(right) == AOP_LIT){
7224                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7225                 if(lit == 0L){
7226                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7227                     pic16_emitcode("cpl","c");
7228                 } else if(lit == 1L) {
7229                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7230                 } else {
7231                     pic16_emitcode("clr","c");
7232                 }
7233                 /* AOP_TYPE(right) == AOP_CRY */
7234             } else {
7235                 symbol *lbl = newiTempLabel(NULL);
7236                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7237                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7238                 pic16_emitcode("cpl","c");
7239                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7240             }
7241             /* if true label then we jump if condition
7242             supplied is true */
7243             tlbl = newiTempLabel(NULL);
7244             if ( IC_TRUE(ifx) ) {
7245                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7246                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7247             } else {
7248                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7249                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7250             }
7251             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7252
7253                 {
7254                 /* left and right are both bit variables, result is carry */
7255                         resolvedIfx rIfx;
7256               
7257                         resolveIfx(&rIfx,ifx);
7258
7259                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7260                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7261                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7262                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7263                         genSkipz2(&rIfx,0);
7264                 }
7265         } else {
7266
7267                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7268
7269                         /* They're not both bit variables. Is the right a literal? */
7270                         if(AOP_TYPE(right) == AOP_LIT) {
7271                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7272             
7273                         switch(size) {
7274
7275                                 case 1:
7276                                         switch(lit & 0xff) {
7277                                                 case 1:
7278                                                                 if ( IC_TRUE(ifx) ) {
7279                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7280                                                                         emitSKPNZ;
7281                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7282                                                                 } else {
7283                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7284                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7285                                                                 }
7286                                                                 break;
7287                                                 case 0xff:
7288                                                                 if ( IC_TRUE(ifx) ) {
7289                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7290                                                                         emitSKPNZ;
7291                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7292                                                                 } else {
7293                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7294                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7295                                                                 }
7296                                                                 break;
7297                                                 default:
7298                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7299                                                                 if(lit)
7300                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7301                                                                 genSkip(ifx,'z');
7302                                         } // switch lit
7303
7304
7305                                         /* end of size == 1 */
7306                                         break;
7307               
7308                                 case 2:
7309                                         genc16bit2lit(left,lit,offset);
7310                                         genSkip(ifx,'z');
7311                                         break;
7312                                         /* end of size == 2 */
7313
7314                                 default:
7315                                         /* size is 4 */
7316                                         if(lit==0) {
7317                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7318                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7319                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7320                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7321                                                 genSkip(ifx,'z');
7322                                         } else {
7323                                                 /* search for patterns that can be optimized */
7324
7325                                                 genc16bit2lit(left,lit,0);
7326                                                 lit >>= 16;
7327                                                 if(lit) {
7328                                                                 if(IC_TRUE(ifx))
7329                                                                 emitSKPZ; // if hi word unequal
7330                                                                 else
7331                                                                 emitSKPNZ; // if hi word equal
7332                                                                 // fail early
7333                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7334                                                         genc16bit2lit(left,lit,2);
7335                                                         genSkip(ifx,'z');
7336                                                 } else {
7337                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7338                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7339                                                         genSkip(ifx,'z');
7340                                                 }
7341                                         }
7342                                                 pic16_emitpLabel(falselbl->key);
7343                                                 break;
7344
7345                         } // switch size
7346           
7347                         ifx->generated = 1;
7348                         goto release ;
7349             
7350
7351           } else if(AOP_TYPE(right) == AOP_CRY ) {
7352             /* we know the left is not a bit, but that the right is */
7353             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7354             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7355                       pic16_popGet(AOP(right),offset));
7356             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7357
7358             /* if the two are equal, then W will be 0 and the Z bit is set
7359              * we could test Z now, or go ahead and check the high order bytes if
7360              * the variable we're comparing is larger than a byte. */
7361
7362             while(--size)
7363               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7364
7365             if ( IC_TRUE(ifx) ) {
7366               emitSKPNZ;
7367               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7368               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7369             } else {
7370               emitSKPZ;
7371               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7372               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7373             }
7374
7375           } else {
7376             /* They're both variables that are larger than bits */
7377             int s = size;
7378
7379             tlbl = newiTempLabel(NULL);
7380
7381             while(size--) {
7382               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7383               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7384
7385               if ( IC_TRUE(ifx) ) {
7386                 if(size) {
7387                   emitSKPZ;
7388                 
7389                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7390
7391                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7392                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7393                 } else {
7394                   emitSKPNZ;
7395
7396                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7397
7398
7399                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7400                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7401                 }
7402               } else {
7403                 emitSKPZ;
7404
7405                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7406
7407                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7408                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7409               }
7410               offset++;
7411             }
7412             if(s>1 && IC_TRUE(ifx)) {
7413               pic16_emitpLabel(tlbl->key);
7414               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7415             }
7416           }
7417         }
7418         /* mark the icode as generated */
7419         ifx->generated = 1;
7420         goto release ;
7421     }
7422
7423     /* if they are both bit variables */
7424     if (AOP_TYPE(left) == AOP_CRY &&
7425         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7426         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7427         if(AOP_TYPE(right) == AOP_LIT){
7428             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7429             if(lit == 0L){
7430                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7431                 pic16_emitcode("cpl","c");
7432             } else if(lit == 1L) {
7433                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7434             } else {
7435                 pic16_emitcode("clr","c");
7436             }
7437             /* AOP_TYPE(right) == AOP_CRY */
7438         } else {
7439             symbol *lbl = newiTempLabel(NULL);
7440             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7441             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7442             pic16_emitcode("cpl","c");
7443             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7444         }
7445         /* c = 1 if egal */
7446         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7447             pic16_outBitC(result);
7448             goto release ;
7449         }
7450         if (ifx) {
7451             genIfxJump (ifx,"c");
7452             goto release ;
7453         }
7454         /* if the result is used in an arithmetic operation
7455         then put the result in place */
7456         pic16_outBitC(result);
7457     } else {
7458       
7459       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7460       gencjne(left,right,result,ifx);
7461 /*
7462       if(ifx) 
7463         gencjne(left,right,newiTempLabel(NULL));
7464       else {
7465         if(IC_TRUE(ifx)->key)
7466           gencjne(left,right,IC_TRUE(ifx)->key);
7467         else
7468           gencjne(left,right,IC_FALSE(ifx)->key);
7469         ifx->generated = 1;
7470         goto release ;
7471       }
7472       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7473         pic16_aopPut(AOP(result),"a",0);
7474         goto release ;
7475       }
7476
7477       if (ifx) {
7478         genIfxJump (ifx,"a");
7479         goto release ;
7480       }
7481 */
7482       /* if the result is used in an arithmetic operation
7483          then put the result in place */
7484 /*
7485       if (AOP_TYPE(result) != AOP_CRY) 
7486         pic16_outAcc(result);
7487 */
7488       /* leave the result in acc */
7489     }
7490
7491 release:
7492     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7493     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7494     pic16_freeAsmop(result,NULL,ic,TRUE);
7495 }
7496 #endif
7497
7498 /*-----------------------------------------------------------------*/
7499 /* ifxForOp - returns the icode containing the ifx for operand     */
7500 /*-----------------------------------------------------------------*/
7501 static iCode *ifxForOp ( operand *op, iCode *ic )
7502 {
7503   FENTRY2;
7504
7505     /* if true symbol then needs to be assigned */
7506     if (IS_TRUE_SYMOP(op))
7507         return NULL ;
7508
7509     /* if this has register type condition and
7510     the next instruction is ifx with the same operand
7511     and live to of the operand is upto the ifx only then */
7512     if (ic->next
7513         && ic->next->op == IFX
7514         && IC_COND(ic->next)->key == op->key
7515         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7516         ) {
7517                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7518           return ic->next;
7519     }
7520
7521     /*
7522     if (ic->next &&
7523         ic->next->op == IFX &&
7524         IC_COND(ic->next)->key == op->key) {
7525       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7526       return ic->next;
7527     }
7528     */
7529
7530     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7531     if (ic->next &&
7532         ic->next->op == IFX)
7533       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7534
7535     if (ic->next &&
7536         ic->next->op == IFX &&
7537         IC_COND(ic->next)->key == op->key) {
7538       DEBUGpic16_emitcode ("; "," key is okay");
7539       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7540                            OP_SYMBOL(op)->liveTo,
7541                            ic->next->seq);
7542     }
7543
7544 #if 0
7545     /* the code below is completely untested
7546      * it just allows ulong2fs.c compile -- VR */
7547          
7548     ic = ic->next;
7549     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7550                                         __FILE__, __FUNCTION__, __LINE__);
7551         
7552     /* if this has register type condition and
7553     the next instruction is ifx with the same operand
7554     and live to of the operand is upto the ifx only then */
7555     if (ic->next &&
7556         ic->next->op == IFX &&
7557         IC_COND(ic->next)->key == op->key &&
7558         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7559         return ic->next;
7560
7561     if (ic->next &&
7562         ic->next->op == IFX &&
7563         IC_COND(ic->next)->key == op->key) {
7564       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7565       return ic->next;
7566     }
7567
7568     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7569                                         __FILE__, __FUNCTION__, __LINE__);
7570
7571 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7572 #endif
7573
7574     return NULL;
7575 }
7576 /*-----------------------------------------------------------------*/
7577 /* genAndOp - for && operation                                     */
7578 /*-----------------------------------------------------------------*/
7579 static void genAndOp (iCode *ic)
7580 {
7581   operand *left,*right, *result;
7582 /*     symbol *tlbl; */
7583
7584     FENTRY;
7585
7586     /* note here that && operations that are in an
7587     if statement are taken away by backPatchLabels
7588     only those used in arthmetic operations remain */
7589     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7590     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7591     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7592
7593     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7594
7595     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7596     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7597     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7598
7599     /* if both are bit variables */
7600 /*     if (AOP_TYPE(left) == AOP_CRY && */
7601 /*         AOP_TYPE(right) == AOP_CRY ) { */
7602 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7603 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7604 /*         pic16_outBitC(result); */
7605 /*     } else { */
7606 /*         tlbl = newiTempLabel(NULL); */
7607 /*         pic16_toBoolean(left);     */
7608 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7609 /*         pic16_toBoolean(right); */
7610 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7611 /*         pic16_outBitAcc(result); */
7612 /*     } */
7613
7614     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7615     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7616     pic16_freeAsmop(result,NULL,ic,TRUE);
7617 }
7618
7619
7620 /*-----------------------------------------------------------------*/
7621 /* genOrOp - for || operation                                      */
7622 /*-----------------------------------------------------------------*/
7623 /*
7624   tsd pic port -
7625   modified this code, but it doesn't appear to ever get called
7626 */
7627
7628 static void genOrOp (iCode *ic)
7629 {
7630   operand *left,*right, *result;
7631   symbol *tlbl;
7632
7633     FENTRY;  
7634
7635   /* note here that || operations that are in an
7636     if statement are taken away by backPatchLabels
7637     only those used in arthmetic operations remain */
7638     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7639     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7640     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7641
7642     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7643
7644     /* if both are bit variables */
7645     if (AOP_TYPE(left) == AOP_CRY &&
7646         AOP_TYPE(right) == AOP_CRY ) {
7647       pic16_emitcode("clrc","");
7648       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7649                AOP(left)->aopu.aop_dir,
7650                AOP(left)->aopu.aop_dir);
7651       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7652                AOP(right)->aopu.aop_dir,
7653                AOP(right)->aopu.aop_dir);
7654       pic16_emitcode("setc","");
7655
7656     } else {
7657         tlbl = newiTempLabel(NULL);
7658         pic16_toBoolean(left);
7659         emitSKPZ;
7660         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7661         pic16_toBoolean(right);
7662         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7663
7664         pic16_outBitAcc(result);
7665     }
7666
7667     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7668     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7669     pic16_freeAsmop(result,NULL,ic,TRUE);            
7670 }
7671
7672 /*-----------------------------------------------------------------*/
7673 /* isLiteralBit - test if lit == 2^n                               */
7674 /*-----------------------------------------------------------------*/
7675 static int isLiteralBit(unsigned long lit)
7676 {
7677     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7678     0x100L,0x200L,0x400L,0x800L,
7679     0x1000L,0x2000L,0x4000L,0x8000L,
7680     0x10000L,0x20000L,0x40000L,0x80000L,
7681     0x100000L,0x200000L,0x400000L,0x800000L,
7682     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7683     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7684     int idx;
7685     
7686     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7687     for(idx = 0; idx < 32; idx++)
7688         if(lit == pw[idx])
7689             return idx+1;
7690     return 0;
7691 }
7692
7693 /*-----------------------------------------------------------------*/
7694 /* continueIfTrue -                                                */
7695 /*-----------------------------------------------------------------*/
7696 static void continueIfTrue (iCode *ic)
7697 {
7698   FENTRY;
7699   if(IC_TRUE(ic))
7700     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7701   ic->generated = 1;
7702 }
7703
7704 /*-----------------------------------------------------------------*/
7705 /* jmpIfTrue -                                                     */
7706 /*-----------------------------------------------------------------*/
7707 static void jumpIfTrue (iCode *ic)
7708 {
7709   FENTRY;
7710   if(!IC_TRUE(ic))
7711     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7712   ic->generated = 1;
7713 }
7714
7715 /*-----------------------------------------------------------------*/
7716 /* jmpTrueOrFalse -                                                */
7717 /*-----------------------------------------------------------------*/
7718 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7719 {
7720   // ugly but optimized by peephole
7721   FENTRY;
7722   if(IC_TRUE(ic)){
7723     symbol *nlbl = newiTempLabel(NULL);
7724       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7725       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7726       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7727       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7728   } else {
7729     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7730     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7731   }
7732   ic->generated = 1;
7733 }
7734
7735 /*-----------------------------------------------------------------*/
7736 /* genAnd  - code for and                                          */
7737 /*-----------------------------------------------------------------*/
7738 static void genAnd (iCode *ic, iCode *ifx)
7739 {
7740   operand *left, *right, *result;
7741   int size, offset=0;  
7742   unsigned long lit = 0L;
7743   int bytelit = 0;
7744   resolvedIfx rIfx;
7745
7746     FENTRY;
7747     
7748   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7749   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7750   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7751
7752   resolveIfx(&rIfx,ifx);
7753
7754   /* if left is a literal & right is not then exchange them */
7755   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7756       AOP_NEEDSACC(left)) {
7757     operand *tmp = right ;
7758     right = left;
7759     left = tmp;
7760   }
7761
7762   /* if result = right then exchange them */
7763   if(pic16_sameRegs(AOP(result),AOP(right))){
7764     operand *tmp = right ;
7765     right = left;
7766     left = tmp;
7767   }
7768
7769   /* if right is bit then exchange them */
7770   if (AOP_TYPE(right) == AOP_CRY &&
7771       AOP_TYPE(left) != AOP_CRY){
7772     operand *tmp = right ;
7773     right = left;
7774     left = tmp;
7775   }
7776   if(AOP_TYPE(right) == AOP_LIT)
7777     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7778
7779   size = AOP_SIZE(result);
7780
7781   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7782
7783   // if(bit & yy)
7784   // result = bit & yy;
7785   if (AOP_TYPE(left) == AOP_CRY){
7786     // c = bit & literal;
7787     if(AOP_TYPE(right) == AOP_LIT){
7788       if(lit & 1) {
7789         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7790           // no change
7791           goto release;
7792         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7793       } else {
7794         // bit(result) = 0;
7795         if(size && (AOP_TYPE(result) == AOP_CRY)){
7796           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7797           goto release;
7798         }
7799         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7800           jumpIfTrue(ifx);
7801           goto release;
7802         }
7803         pic16_emitcode("clr","c");
7804       }
7805     } else {
7806       if (AOP_TYPE(right) == AOP_CRY){
7807         // c = bit & bit;
7808         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7809         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7810       } else {
7811         // c = bit & val;
7812         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7813         // c = lsb
7814         pic16_emitcode("rrc","a");
7815         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7816       }
7817     }
7818     // bit = c
7819     // val = c
7820     if(size)
7821       pic16_outBitC(result);
7822     // if(bit & ...)
7823     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7824       genIfxJump(ifx, "c");           
7825     goto release ;
7826   }
7827
7828   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7829   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7830   if((AOP_TYPE(right) == AOP_LIT) &&
7831      (AOP_TYPE(result) == AOP_CRY) &&
7832      (AOP_TYPE(left) != AOP_CRY)){
7833     int posbit = isLiteralBit(lit);
7834     /* left &  2^n */
7835     if(posbit){
7836       posbit--;
7837       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7838       // bit = left & 2^n
7839       if(size)
7840         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7841       // if(left &  2^n)
7842       else{
7843         if(ifx){
7844 /*
7845           if(IC_TRUE(ifx)) {
7846             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7847             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7848           } else {
7849             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7850             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7851           }
7852 */
7853         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7854         size = AOP_SIZE(left);
7855
7856         {
7857           int bp = posbit, ofs=0;
7858           
7859             while(bp > 7) {
7860               bp -= 8;
7861               ofs++;
7862             }
7863         
7864           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7865                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7866
7867         }
7868 /*
7869           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7870                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7871 */
7872           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7873           
7874           ifx->generated = 1;
7875         }
7876         goto release;
7877       }
7878     } else {
7879       symbol *tlbl = newiTempLabel(NULL);
7880       int sizel = AOP_SIZE(left);
7881
7882       if(size)
7883         emitSETC;
7884
7885       while(sizel--) {
7886         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7887
7888           /* patch provided by Aaron Colwell */
7889           if((posbit = isLiteralBit(bytelit)) != 0) {
7890               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7891                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7892                                                 (posbit-1),0, PO_GPR_REGISTER));
7893
7894               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7895 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7896           } else {
7897               if (bytelit == 0xff) {
7898                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7899                    * a peephole could optimize it out -- VR */
7900                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7901               } else {
7902                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7903                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7904               }
7905
7906               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7907                             pic16_popGetLabel(tlbl->key));
7908           }
7909         
7910 #if 0
7911           /* old code, left here for reference -- VR 09/2004 */
7912           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7913           // byte ==  2^n ?
7914           if((posbit = isLiteralBit(bytelit)) != 0)
7915             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7916           else{
7917             if(bytelit != 0x0FFL)
7918               pic16_emitcode("anl","a,%s",
7919                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7920             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7921           }
7922 #endif
7923         }
7924         offset++;
7925       }
7926       // bit = left & literal
7927       if(size) {
7928         emitCLRC;
7929         pic16_emitpLabel(tlbl->key);
7930       }
7931       // if(left & literal)
7932       else {
7933         if(ifx) {
7934           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7935           ifx->generated = 1;
7936         }
7937         pic16_emitpLabel(tlbl->key);
7938         goto release;
7939       }
7940     }
7941
7942     pic16_outBitC(result);
7943     goto release ;
7944   }
7945
7946   /* if left is same as result */
7947   if(pic16_sameRegs(AOP(result),AOP(left))){
7948     int know_W = -1;
7949     for(;size--; offset++,lit>>=8) {
7950       if(AOP_TYPE(right) == AOP_LIT){
7951         switch(lit & 0xff) {
7952         case 0x00:
7953           /*  and'ing with 0 has clears the result */
7954 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7955           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7956           break;
7957         case 0xff:
7958           /* and'ing with 0xff is a nop when the result and left are the same */
7959           break;
7960
7961         default:
7962           {
7963             int p = pic16_my_powof2( (~lit) & 0xff );
7964             if(p>=0) {
7965               /* only one bit is set in the literal, so use a bcf instruction */
7966 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7967               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7968
7969             } else {
7970               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7971               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7972               if(know_W != (lit&0xff))
7973                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7974               know_W = lit &0xff;
7975               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7976             }
7977           }    
7978         }
7979       } else {
7980         if (AOP_TYPE(left) == AOP_ACC) {
7981           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7982         } else {                    
7983           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7984           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7985
7986         }
7987       }
7988     }
7989
7990   } else {
7991     // left & result in different registers
7992     if(AOP_TYPE(result) == AOP_CRY){
7993       // result = bit
7994       // if(size), result in bit
7995       // if(!size && ifx), conditional oper: if(left & right)
7996       symbol *tlbl = newiTempLabel(NULL);
7997       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7998       if(size)
7999         pic16_emitcode("setb","c");
8000       while(sizer--){
8001         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8002         pic16_emitcode("anl","a,%s",
8003                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8004         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8005         offset++;
8006       }
8007       if(size){
8008         CLRC;
8009         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8010         pic16_outBitC(result);
8011       } else if(ifx)
8012         jmpTrueOrFalse(ifx, tlbl);
8013     } else {
8014       for(;(size--);offset++) {
8015         // normal case
8016         // result = left & right
8017         if(AOP_TYPE(right) == AOP_LIT){
8018           int t = (lit >> (offset*8)) & 0x0FFL;
8019           switch(t) { 
8020           case 0x00:
8021             pic16_emitcode("clrf","%s",
8022                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8023             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8024             break;
8025           case 0xff:
8026             pic16_emitcode("movf","%s,w",
8027                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8028             pic16_emitcode("movwf","%s",
8029                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8030             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8031             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8032             break;
8033           default:
8034             pic16_emitcode("movlw","0x%x",t);
8035             pic16_emitcode("andwf","%s,w",
8036                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8037             pic16_emitcode("movwf","%s",
8038                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8039               
8040             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8041             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8042             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8043           }
8044           continue;
8045         }
8046
8047         if (AOP_TYPE(left) == AOP_ACC) {
8048           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8049           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8050         } else {
8051           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8052           pic16_emitcode("andwf","%s,w",
8053                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8054           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8055           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8056         }
8057         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8058         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8059       }
8060     }
8061   }
8062
8063   release :
8064     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8065   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8066   pic16_freeAsmop(result,NULL,ic,TRUE);     
8067 }
8068
8069 /*-----------------------------------------------------------------*/
8070 /* genOr  - code for or                                            */
8071 /*-----------------------------------------------------------------*/
8072 static void genOr (iCode *ic, iCode *ifx)
8073 {
8074     operand *left, *right, *result;
8075     int size, offset=0;
8076     unsigned long lit = 0L;
8077
8078     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8079
8080     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8081     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8082     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8083
8084     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8085
8086     /* if left is a literal & right is not then exchange them */
8087     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8088         AOP_NEEDSACC(left)) {
8089         operand *tmp = right ;
8090         right = left;
8091         left = tmp;
8092     }
8093
8094     /* if result = right then exchange them */
8095     if(pic16_sameRegs(AOP(result),AOP(right))){
8096         operand *tmp = right ;
8097         right = left;
8098         left = tmp;
8099     }
8100
8101     /* if right is bit then exchange them */
8102     if (AOP_TYPE(right) == AOP_CRY &&
8103         AOP_TYPE(left) != AOP_CRY){
8104         operand *tmp = right ;
8105         right = left;
8106         left = tmp;
8107     }
8108
8109     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8110
8111     if(AOP_TYPE(right) == AOP_LIT)
8112         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8113
8114     size = AOP_SIZE(result);
8115
8116     // if(bit | yy)
8117     // xx = bit | yy;
8118     if (AOP_TYPE(left) == AOP_CRY){
8119         if(AOP_TYPE(right) == AOP_LIT){
8120             // c = bit & literal;
8121             if(lit){
8122                 // lit != 0 => result = 1
8123                 if(AOP_TYPE(result) == AOP_CRY){
8124                   if(size)
8125                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8126                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8127                   //     AOP(result)->aopu.aop_dir,
8128                   //     AOP(result)->aopu.aop_dir);
8129                     else if(ifx)
8130                         continueIfTrue(ifx);
8131                     goto release;
8132                 }
8133             } else {
8134                 // lit == 0 => result = left
8135                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8136                     goto release;
8137                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8138             }
8139         } else {
8140             if (AOP_TYPE(right) == AOP_CRY){
8141               if(pic16_sameRegs(AOP(result),AOP(left))){
8142                 // c = bit | bit;
8143                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8144                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8145                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8146
8147                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8148                          AOP(result)->aopu.aop_dir,
8149                          AOP(result)->aopu.aop_dir);
8150                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8151                          AOP(right)->aopu.aop_dir,
8152                          AOP(right)->aopu.aop_dir);
8153                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8154                          AOP(result)->aopu.aop_dir,
8155                          AOP(result)->aopu.aop_dir);
8156               } else {
8157                 if( AOP_TYPE(result) == AOP_ACC) {
8158                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8159                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8160                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8161                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8162
8163                 } else {
8164
8165                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8166                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8167                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8168                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8169
8170                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8171                                  AOP(result)->aopu.aop_dir,
8172                                  AOP(result)->aopu.aop_dir);
8173                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8174                                  AOP(right)->aopu.aop_dir,
8175                                  AOP(right)->aopu.aop_dir);
8176                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8177                                  AOP(left)->aopu.aop_dir,
8178                                  AOP(left)->aopu.aop_dir);
8179                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8180                                  AOP(result)->aopu.aop_dir,
8181                                  AOP(result)->aopu.aop_dir);
8182                 }
8183               }
8184             } else {
8185                 // c = bit | val;
8186                 symbol *tlbl = newiTempLabel(NULL);
8187                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8188
8189
8190                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8191                 if( AOP_TYPE(right) == AOP_ACC) {
8192                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8193                   emitSKPNZ;
8194                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8195                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8196                 }
8197
8198
8199
8200                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8201                     pic16_emitcode(";XXX setb","c");
8202                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8203                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8204                 pic16_toBoolean(right);
8205                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8206                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8207                     jmpTrueOrFalse(ifx, tlbl);
8208                     goto release;
8209                 } else {
8210                     CLRC;
8211                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8212                 }
8213             }
8214         }
8215         // bit = c
8216         // val = c
8217         if(size)
8218             pic16_outBitC(result);
8219         // if(bit | ...)
8220         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8221             genIfxJump(ifx, "c");           
8222         goto release ;
8223     }
8224
8225     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8226     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8227     if((AOP_TYPE(right) == AOP_LIT) &&
8228        (AOP_TYPE(result) == AOP_CRY) &&
8229        (AOP_TYPE(left) != AOP_CRY)){
8230         if(lit){
8231           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8232             // result = 1
8233             if(size)
8234                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8235             else 
8236                 continueIfTrue(ifx);
8237             goto release;
8238         } else {
8239           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8240             // lit = 0, result = boolean(left)
8241             if(size)
8242                 pic16_emitcode(";XXX setb","c");
8243             pic16_toBoolean(right);
8244             if(size){
8245                 symbol *tlbl = newiTempLabel(NULL);
8246                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8247                 CLRC;
8248                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8249             } else {
8250                 genIfxJump (ifx,"a");
8251                 goto release;
8252             }
8253         }
8254         pic16_outBitC(result);
8255         goto release ;
8256     }
8257
8258     /* if left is same as result */
8259     if(pic16_sameRegs(AOP(result),AOP(left))){
8260       int know_W = -1;
8261       for(;size--; offset++,lit>>=8) {
8262         if(AOP_TYPE(right) == AOP_LIT){
8263           if((lit & 0xff) == 0)
8264             /*  or'ing with 0 has no effect */
8265             continue;
8266           else {
8267             int p = pic16_my_powof2(lit & 0xff);
8268             if(p>=0) {
8269               /* only one bit is set in the literal, so use a bsf instruction */
8270               pic16_emitpcode(POC_BSF,
8271                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8272             } else {
8273               if(know_W != (lit & 0xff))
8274                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8275               know_W = lit & 0xff;
8276               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8277             }
8278                     
8279           }
8280         } else {
8281           if (AOP_TYPE(left) == AOP_ACC) {
8282             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8283             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8284           } else {                  
8285             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8286             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8287
8288             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8289             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8290
8291           }
8292         }
8293       }
8294     } else {
8295         // left & result in different registers
8296         if(AOP_TYPE(result) == AOP_CRY){
8297             // result = bit
8298             // if(size), result in bit
8299             // if(!size && ifx), conditional oper: if(left | right)
8300             symbol *tlbl = newiTempLabel(NULL);
8301             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8302             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8303
8304
8305             if(size)
8306                 pic16_emitcode(";XXX setb","c");
8307             while(sizer--){
8308                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8309                 pic16_emitcode(";XXX orl","a,%s",
8310                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8311                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8312                 offset++;
8313             }
8314             if(size){
8315                 CLRC;
8316                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8317                 pic16_outBitC(result);
8318             } else if(ifx)
8319                 jmpTrueOrFalse(ifx, tlbl);
8320         } else for(;(size--);offset++){
8321           // normal case
8322           // result = left & right
8323           if(AOP_TYPE(right) == AOP_LIT){
8324             int t = (lit >> (offset*8)) & 0x0FFL;
8325             switch(t) { 
8326             case 0x00:
8327               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8328               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8329
8330               pic16_emitcode("movf","%s,w",
8331                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8332               pic16_emitcode("movwf","%s",
8333                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8334               break;
8335             default:
8336               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8337               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8338               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8339
8340               pic16_emitcode("movlw","0x%x",t);
8341               pic16_emitcode("iorwf","%s,w",
8342                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8343               pic16_emitcode("movwf","%s",
8344                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8345               
8346             }
8347             continue;
8348           }
8349
8350           // faster than result <- left, anl result,right
8351           // and better if result is SFR
8352           if (AOP_TYPE(left) == AOP_ACC) {
8353             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8354             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8355           } else {
8356             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8357             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8358
8359             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8360             pic16_emitcode("iorwf","%s,w",
8361                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8362           }
8363           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8364           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8365         }
8366     }
8367
8368 release :
8369     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8370     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8371     pic16_freeAsmop(result,NULL,ic,TRUE);     
8372 }
8373
8374 /*-----------------------------------------------------------------*/
8375 /* genXor - code for xclusive or                                   */
8376 /*-----------------------------------------------------------------*/
8377 static void genXor (iCode *ic, iCode *ifx)
8378 {
8379   operand *left, *right, *result;
8380   int size, offset=0;
8381   unsigned long lit = 0L;
8382
8383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8384
8385   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8386   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8387   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8388
8389   /* if left is a literal & right is not ||
8390      if left needs acc & right does not */
8391   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8392       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8393     operand *tmp = right ;
8394     right = left;
8395     left = tmp;
8396   }
8397
8398   /* if result = right then exchange them */
8399   if(pic16_sameRegs(AOP(result),AOP(right))){
8400     operand *tmp = right ;
8401     right = left;
8402     left = tmp;
8403   }
8404
8405   /* if right is bit then exchange them */
8406   if (AOP_TYPE(right) == AOP_CRY &&
8407       AOP_TYPE(left) != AOP_CRY){
8408     operand *tmp = right ;
8409     right = left;
8410     left = tmp;
8411   }
8412   if(AOP_TYPE(right) == AOP_LIT)
8413     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8414
8415   size = AOP_SIZE(result);
8416
8417   // if(bit ^ yy)
8418   // xx = bit ^ yy;
8419   if (AOP_TYPE(left) == AOP_CRY){
8420     if(AOP_TYPE(right) == AOP_LIT){
8421       // c = bit & literal;
8422       if(lit>>1){
8423         // lit>>1  != 0 => result = 1
8424         if(AOP_TYPE(result) == AOP_CRY){
8425           if(size)
8426             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8427             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8428           else if(ifx)
8429             continueIfTrue(ifx);
8430           goto release;
8431         }
8432         pic16_emitcode("setb","c");
8433       } else{
8434         // lit == (0 or 1)
8435         if(lit == 0){
8436           // lit == 0, result = left
8437           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8438             goto release;
8439           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8440         } else{
8441           // lit == 1, result = not(left)
8442           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8443             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8444             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8445             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8446             goto release;
8447           } else {
8448             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8449             pic16_emitcode("cpl","c");
8450           }
8451         }
8452       }
8453
8454     } else {
8455       // right != literal
8456       symbol *tlbl = newiTempLabel(NULL);
8457       if (AOP_TYPE(right) == AOP_CRY){
8458         // c = bit ^ bit;
8459         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8460       }
8461       else{
8462         int sizer = AOP_SIZE(right);
8463         // c = bit ^ val
8464         // if val>>1 != 0, result = 1
8465         pic16_emitcode("setb","c");
8466         while(sizer){
8467           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8468           if(sizer == 1)
8469             // test the msb of the lsb
8470             pic16_emitcode("anl","a,#0xfe");
8471           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8472           sizer--;
8473         }
8474         // val = (0,1)
8475         pic16_emitcode("rrc","a");
8476       }
8477       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8478       pic16_emitcode("cpl","c");
8479       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8480     }
8481     // bit = c
8482     // val = c
8483     if(size)
8484       pic16_outBitC(result);
8485     // if(bit | ...)
8486     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8487       genIfxJump(ifx, "c");           
8488     goto release ;
8489   }
8490
8491   if(pic16_sameRegs(AOP(result),AOP(left))){
8492     /* if left is same as result */
8493     for(;size--; offset++) {
8494       if(AOP_TYPE(right) == AOP_LIT){
8495         int t  = (lit >> (offset*8)) & 0x0FFL;
8496         if(t == 0x00L)
8497           continue;
8498         else
8499           if (IS_AOP_PREG(left)) {
8500             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8501             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8502             pic16_aopPut(AOP(result),"a",offset);
8503           } else {
8504             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8505             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8506             pic16_emitcode("xrl","%s,%s",
8507                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8508                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8509           }
8510       } else {
8511         if (AOP_TYPE(left) == AOP_ACC)
8512           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8513         else {
8514           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8515           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8516 /*
8517           if (IS_AOP_PREG(left)) {
8518             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8519             pic16_aopPut(AOP(result),"a",offset);
8520           } else
8521             pic16_emitcode("xrl","%s,a",
8522                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8523 */
8524         }
8525       }
8526     }
8527   } else {
8528     // left & result in different registers
8529     if(AOP_TYPE(result) == AOP_CRY){
8530       // result = bit
8531       // if(size), result in bit
8532       // if(!size && ifx), conditional oper: if(left ^ right)
8533       symbol *tlbl = newiTempLabel(NULL);
8534       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8535       if(size)
8536         pic16_emitcode("setb","c");
8537       while(sizer--){
8538         if((AOP_TYPE(right) == AOP_LIT) &&
8539            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8540           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8541         } else {
8542           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8543           pic16_emitcode("xrl","a,%s",
8544                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8545         }
8546         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8547         offset++;
8548       }
8549       if(size){
8550         CLRC;
8551         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8552         pic16_outBitC(result);
8553       } else if(ifx)
8554         jmpTrueOrFalse(ifx, tlbl);
8555     } else for(;(size--);offset++){
8556       // normal case
8557       // result = left & right
8558       if(AOP_TYPE(right) == AOP_LIT){
8559         int t = (lit >> (offset*8)) & 0x0FFL;
8560         switch(t) { 
8561         case 0x00:
8562           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8563           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8564           pic16_emitcode("movf","%s,w",
8565                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8566           pic16_emitcode("movwf","%s",
8567                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8568           break;
8569         case 0xff:
8570           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8571           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8572           pic16_emitcode("comf","%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         default:
8578           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8579           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8580           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8581           pic16_emitcode("movlw","0x%x",t);
8582           pic16_emitcode("xorwf","%s,w",
8583                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8584           pic16_emitcode("movwf","%s",
8585                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8586
8587         }
8588         continue;
8589       }
8590
8591       // faster than result <- left, anl result,right
8592       // and better if result is SFR
8593       if (AOP_TYPE(left) == AOP_ACC) {
8594         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8595         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8596       } else {
8597         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8598         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8599         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8600         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8601       }
8602       if ( AOP_TYPE(result) != AOP_ACC){
8603         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8604         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8605       }
8606     }
8607   }
8608
8609   release :
8610     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8611   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8612   pic16_freeAsmop(result,NULL,ic,TRUE);     
8613 }
8614
8615 /*-----------------------------------------------------------------*/
8616 /* genInline - write the inline code out                           */
8617 /*-----------------------------------------------------------------*/
8618 static void genInline (iCode *ic)
8619 {
8620   char *buffer, *bp, *bp1;
8621     
8622         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8623
8624         _G.inLine += (!options.asmpeep);
8625
8626         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8627         strcpy(buffer,IC_INLINE(ic));
8628
8629 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8630
8631         /* emit each line as a code */
8632         while (*bp) {
8633                 if (*bp == '\n') {
8634                         *bp++ = '\0';
8635
8636                         if(*bp1)
8637                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8638                         bp1 = bp;
8639                 } else {
8640                         if (*bp == ':') {
8641                                 bp++;
8642                                 *bp = '\0';
8643                                 bp++;
8644
8645                                 /* print label, use this special format with NULL directive
8646                                  * to denote that the argument should not be indented with tab */
8647                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8648                                 bp1 = bp;
8649                         } else
8650                                 bp++;
8651                 }
8652         }
8653
8654         if ((bp1 != bp) && *bp1)
8655                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8656
8657
8658     Safe_free(buffer);
8659
8660     _G.inLine -= (!options.asmpeep);
8661 }
8662
8663 /*-----------------------------------------------------------------*/
8664 /* genRRC - rotate right with carry                                */
8665 /*-----------------------------------------------------------------*/
8666 static void genRRC (iCode *ic)
8667 {
8668   operand *left , *result ;
8669   int size, offset = 0, same;
8670
8671   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8672
8673   /* rotate right with carry */
8674   left = IC_LEFT(ic);
8675   result=IC_RESULT(ic);
8676   pic16_aopOp (left,ic,FALSE);
8677   pic16_aopOp (result,ic,FALSE);
8678
8679   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8680
8681   same = pic16_sameRegs(AOP(result),AOP(left));
8682
8683   size = AOP_SIZE(result);    
8684
8685   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8686
8687   /* get the lsb and put it into the carry */
8688   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8689
8690   offset = 0 ;
8691
8692   while(size--) {
8693
8694     if(same) {
8695       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8696     } else {
8697       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8698       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8699     }
8700
8701     offset++;
8702   }
8703
8704   pic16_freeAsmop(left,NULL,ic,TRUE);
8705   pic16_freeAsmop(result,NULL,ic,TRUE);
8706 }
8707
8708 /*-----------------------------------------------------------------*/
8709 /* genRLC - generate code for rotate left with carry               */
8710 /*-----------------------------------------------------------------*/
8711 static void genRLC (iCode *ic)
8712 {    
8713   operand *left , *result ;
8714   int size, offset = 0;
8715   int same;
8716
8717   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8718   /* rotate right with carry */
8719   left = IC_LEFT(ic);
8720   result=IC_RESULT(ic);
8721   pic16_aopOp (left,ic,FALSE);
8722   pic16_aopOp (result,ic,FALSE);
8723
8724   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8725
8726   same = pic16_sameRegs(AOP(result),AOP(left));
8727
8728   /* move it to the result */
8729   size = AOP_SIZE(result);    
8730
8731   /* get the msb and put it into the carry */
8732   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8733
8734   offset = 0 ;
8735
8736   while(size--) {
8737
8738     if(same) {
8739       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8740     } else {
8741       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8742       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8743     }
8744
8745     offset++;
8746   }
8747
8748
8749   pic16_freeAsmop(left,NULL,ic,TRUE);
8750   pic16_freeAsmop(result,NULL,ic,TRUE);
8751 }
8752
8753
8754 /* gpasm can get the highest order bit with HIGH/UPPER
8755  * so the following probably is not needed -- VR */
8756  
8757 /*-----------------------------------------------------------------*/
8758 /* genGetHbit - generates code get highest order bit               */
8759 /*-----------------------------------------------------------------*/
8760 static void genGetHbit (iCode *ic)
8761 {
8762     operand *left, *result;
8763     left = IC_LEFT(ic);
8764     result=IC_RESULT(ic);
8765     pic16_aopOp (left,ic,FALSE);
8766     pic16_aopOp (result,ic,FALSE);
8767
8768     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8769     /* get the highest order byte into a */
8770     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8771     if(AOP_TYPE(result) == AOP_CRY){
8772         pic16_emitcode("rlc","a");
8773         pic16_outBitC(result);
8774     }
8775     else{
8776         pic16_emitcode("rl","a");
8777         pic16_emitcode("anl","a,#0x01");
8778         pic16_outAcc(result);
8779     }
8780
8781
8782     pic16_freeAsmop(left,NULL,ic,TRUE);
8783     pic16_freeAsmop(result,NULL,ic,TRUE);
8784 }
8785
8786 #if 0
8787 /*-----------------------------------------------------------------*/
8788 /* AccRol - rotate left accumulator by known count                 */
8789 /*-----------------------------------------------------------------*/
8790 static void AccRol (int shCount)
8791 {
8792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8793     shCount &= 0x0007;              // shCount : 0..7
8794     switch(shCount){
8795         case 0 :
8796             break;
8797         case 1 :
8798             pic16_emitcode("rl","a");
8799             break;
8800         case 2 :
8801             pic16_emitcode("rl","a");
8802             pic16_emitcode("rl","a");
8803             break;
8804         case 3 :
8805             pic16_emitcode("swap","a");
8806             pic16_emitcode("rr","a");
8807             break;
8808         case 4 :
8809             pic16_emitcode("swap","a");
8810             break;
8811         case 5 :
8812             pic16_emitcode("swap","a");
8813             pic16_emitcode("rl","a");
8814             break;
8815         case 6 :
8816             pic16_emitcode("rr","a");
8817             pic16_emitcode("rr","a");
8818             break;
8819         case 7 :
8820             pic16_emitcode("rr","a");
8821             break;
8822     }
8823 }
8824 #endif
8825
8826 /*-----------------------------------------------------------------*/
8827 /* AccLsh - left shift accumulator by known count                  */
8828 /*-----------------------------------------------------------------*/
8829 static void AccLsh (int shCount)
8830 {
8831         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8832         switch(shCount){
8833                 case 0 :
8834                         return;
8835                         break;
8836                 case 1 :
8837                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8838                         break;
8839                 case 2 :
8840                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8841                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8842                         break;
8843                 case 3 :
8844                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8845                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8846                         break;
8847                 case 4 :
8848                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8849                         break;
8850                 case 5 :
8851                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8852                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8853                         break;
8854                 case 6 :
8855                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8856                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8857                         break;
8858                 case 7 :
8859                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8860                         break;
8861         }
8862
8863         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8864 }
8865
8866 /*-----------------------------------------------------------------*/
8867 /* AccRsh - right shift accumulator by known count                 */
8868 /*-----------------------------------------------------------------*/
8869 static void AccRsh (int shCount, int andmask)
8870 {
8871         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8872         switch(shCount){
8873                 case 0 :
8874                         return; break;
8875                 case 1 :
8876                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8877                         break;
8878                 case 2 :
8879                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8880                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8881                         break;
8882                 case 3 :
8883                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8884                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8885                         break;
8886                 case 4 :
8887                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8888                         break;
8889                 case 5 :
8890                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8891                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8892                         break;
8893                 case 6 :
8894                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8895                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8896                         break;
8897                 case 7 :
8898                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8899                         break;
8900         }
8901         
8902         if(andmask)
8903                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8904         else
8905                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8906 }
8907
8908 #if 0
8909 /*-----------------------------------------------------------------*/
8910 /* AccSRsh - signed right shift accumulator by known count                 */
8911 /*-----------------------------------------------------------------*/
8912 static void AccSRsh (int shCount)
8913 {
8914     symbol *tlbl ;
8915     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8916     if(shCount != 0){
8917         if(shCount == 1){
8918             pic16_emitcode("mov","c,acc.7");
8919             pic16_emitcode("rrc","a");
8920         } else if(shCount == 2){
8921             pic16_emitcode("mov","c,acc.7");
8922             pic16_emitcode("rrc","a");
8923             pic16_emitcode("mov","c,acc.7");
8924             pic16_emitcode("rrc","a");
8925         } else {
8926             tlbl = newiTempLabel(NULL);
8927             /* rotate right accumulator */
8928             AccRol(8 - shCount);
8929             /* and kill the higher order bits */
8930             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8931             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8932             pic16_emitcode("orl","a,#0x%02x",
8933                      (unsigned char)~SRMask[shCount]);
8934             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8935         }
8936     }
8937 }
8938 #endif
8939
8940 /*-----------------------------------------------------------------*/
8941 /* shiftR1Left2Result - shift right one byte from left to result   */
8942 /*-----------------------------------------------------------------*/
8943 static void shiftR1Left2ResultSigned (operand *left, int offl,
8944                                 operand *result, int offr,
8945                                 int shCount)
8946 {
8947   int same;
8948
8949   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8950
8951   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8952
8953   switch(shCount) {
8954   case 1:
8955     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8956     if(same) 
8957       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8958     else {
8959       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8960       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8961     }
8962
8963     break;
8964   case 2:
8965
8966     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8967     if(same) 
8968       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8969     else {
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8971       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8972     }
8973     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8974     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8975
8976     break;
8977
8978   case 3:
8979     if(same)
8980       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8981     else {
8982       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8983       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8984     }
8985
8986     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8987     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8988     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8989
8990     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8991     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8992
8993     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8994     break;
8995
8996   case 4:
8997     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8998     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8999     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9000     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
9001     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9002     break;
9003   case 5:
9004     if(same) {
9005       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
9006     } else {
9007       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
9008       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9009     }
9010     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
9011     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
9012     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9013     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
9014     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9015     break;
9016
9017   case 6:
9018     if(same) {
9019       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9020       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9021       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9022       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9023       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9025     } else {
9026       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9028       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9030       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9031     }
9032     break;
9033
9034   case 7:
9035     if(same) {
9036       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9037       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9038       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9039       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040     } else {
9041       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9042       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9043       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9044     }
9045
9046   default:
9047     break;
9048   }
9049 }
9050
9051 /*-----------------------------------------------------------------*/
9052 /* shiftR1Left2Result - shift right one byte from left to result   */
9053 /*-----------------------------------------------------------------*/
9054 static void shiftR1Left2Result (operand *left, int offl,
9055                                 operand *result, int offr,
9056                                 int shCount, int sign)
9057 {
9058   int same;
9059
9060   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9061
9062   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9063
9064   /* Copy the msb into the carry if signed. */
9065   if(sign) {
9066     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9067     return;
9068   }
9069
9070
9071
9072   switch(shCount) {
9073   case 1:
9074     emitCLRC;
9075     if(same) 
9076       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9077     else {
9078       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9079       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9080     }
9081     break;
9082   case 2:
9083     emitCLRC;
9084     if(same) {
9085       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9086     } else {
9087       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9088       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9089     }
9090     emitCLRC;
9091     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9092
9093     break;
9094   case 3:
9095     if(same)
9096       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9097     else {
9098       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9099       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9100     }
9101
9102     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9103     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9104     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9105     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9106     break;
9107       
9108   case 4:
9109     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9110     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9111     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9112     break;
9113
9114   case 5:
9115     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9116     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9117     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9118     //emitCLRC;
9119     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9120
9121     break;
9122   case 6:
9123
9124     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9125     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9126     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9127     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9128     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9129     break;
9130
9131   case 7:
9132
9133     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9134     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9135     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9136
9137     break;
9138
9139   default:
9140     break;
9141   }
9142 }
9143
9144 /*-----------------------------------------------------------------*/
9145 /* shiftL1Left2Result - shift left one byte from left to result    */
9146 /*-----------------------------------------------------------------*/
9147 static void shiftL1Left2Result (operand *left, int offl,
9148                                 operand *result, int offr, int shCount)
9149 {
9150   int same;
9151
9152   //    char *l;
9153   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9154
9155   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9156   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9157     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9158     //    MOVA(l);
9159     /* shift left accumulator */
9160     //AccLsh(shCount); // don't comment out just yet...
9161   //    pic16_aopPut(AOP(result),"a",offr);
9162
9163   switch(shCount) {
9164   case 1:
9165     /* Shift left 1 bit position */
9166     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9167     if(same) {
9168       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9169     } else {
9170       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9171       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9172     }
9173     break;
9174   case 2:
9175     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9176     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9177     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9178     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9179     break;
9180   case 3:
9181     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9182     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9183     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9184     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9185     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9186     break;
9187   case 4:
9188     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9189     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9190     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9191     break;
9192   case 5:
9193     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9194     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9195     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9196     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9197     break;
9198   case 6:
9199     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9200     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9201     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9202     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9203     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9204     break;
9205   case 7:
9206     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9207     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9208     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9209     break;
9210
9211   default:
9212     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9213   }
9214
9215 }
9216
9217 /*-----------------------------------------------------------------*/
9218 /* movLeft2Result - move byte from left to result                  */
9219 /*-----------------------------------------------------------------*/
9220 static void movLeft2Result (operand *left, int offl,
9221                             operand *result, int offr)
9222 {
9223   char *l;
9224   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9225   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9226     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9227
9228     if (*l == '@' && (IS_AOP_PREG(result))) {
9229       pic16_emitcode("mov","a,%s",l);
9230       pic16_aopPut(AOP(result),"a",offr);
9231     } else {
9232       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9233       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9234     }
9235   }
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* shiftL2Left2Result - shift left two bytes from left to result   */
9240 /*-----------------------------------------------------------------*/
9241 static void shiftL2Left2Result (operand *left, int offl,
9242                                 operand *result, int offr, int shCount)
9243 {
9244   int same = pic16_sameRegs(AOP(result), AOP(left));
9245   int i;
9246
9247   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9248
9249   if (same && (offl != offr)) { // shift bytes
9250     if (offr > offl) {
9251        for(i=1;i>-1;i--) {
9252          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9253          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9254        }
9255     } else { // just treat as different later on
9256                 same = 0;
9257     }
9258   }
9259
9260   if(same) {
9261     switch(shCount) {
9262     case 0:
9263       break;
9264     case 1:
9265     case 2:
9266     case 3:
9267
9268       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9269       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9270       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9271
9272       while(--shCount) {
9273                 emitCLRC;
9274                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9275                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9276       }
9277
9278       break;
9279     case 4:
9280     case 5:
9281       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9282       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9283       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9284       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9285       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9286       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9287       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9288       if(shCount >=5) {
9289                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9290                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9291       }
9292       break;
9293     case 6:
9294       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9295       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9296       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9297       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9298       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9299       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9300       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9301       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9302       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9303       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9304       break;
9305     case 7:
9306       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9307       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9308       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9309       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9310       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9311     }
9312
9313   } else {
9314     switch(shCount) {
9315     case 0:
9316       break;
9317     case 1:
9318     case 2:
9319     case 3:
9320       /* note, use a mov/add for the shift since the mov has a
9321          chance of getting optimized out */
9322       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9323       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9324       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9325       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9326       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9327
9328       while(--shCount) {
9329                 emitCLRC;
9330                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9331                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9332       }
9333       break;
9334
9335     case 4:
9336     case 5:
9337       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9338       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9339       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9340       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9341       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9342       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9343       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9344       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9345
9346
9347       if(shCount == 5) {
9348                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9349                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9350       }
9351       break;
9352     case 6:
9353       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9354       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9355       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9356       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9357
9358       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9359       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9360       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9361       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9362       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9363       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9364       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9365       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9366       break;
9367     case 7:
9368       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9370       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9372       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9373     }
9374   }
9375
9376 }
9377 /*-----------------------------------------------------------------*/
9378 /* shiftR2Left2Result - shift right two bytes from left to result  */
9379 /*-----------------------------------------------------------------*/
9380 static void shiftR2Left2Result (operand *left, int offl,
9381                                 operand *result, int offr,
9382                                 int shCount, int sign)
9383 {
9384   int same = pic16_sameRegs(AOP(result), AOP(left));
9385   int i;
9386   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9387
9388   if (same && (offl != offr)) { // shift right bytes
9389     if (offr < offl) {
9390        for(i=0;i<2;i++) {
9391          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9392          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9393        }
9394     } else { // just treat as different later on
9395                 same = 0;
9396     }
9397   }
9398
9399   switch(shCount) {
9400   case 0:
9401     break;
9402   case 1:
9403   case 2:
9404   case 3:
9405     if(sign)
9406       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9407     else
9408       emitCLRC;
9409
9410     if(same) {
9411       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9412       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9413     } else {
9414       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9415       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9416       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9417       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9418     }
9419
9420     while(--shCount) {
9421       if(sign)
9422                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9423       else
9424                 emitCLRC;
9425       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9426       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9427     }
9428     break;
9429   case 4:
9430   case 5:
9431     if(same) {
9432
9433       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9434       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9435       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9436
9437       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9438       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9439       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9440       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9441     } else {
9442       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9443       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9444       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9445
9446       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9447       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9448       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9449       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9450       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9451     }
9452
9453     if(shCount >=5) {
9454       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9455       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9456     }
9457
9458     if(sign) {
9459       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9460       pic16_emitpcode(POC_BTFSC, 
9461                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9462       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9463     }
9464
9465     break;
9466
9467   case 6:
9468     if(same) {
9469
9470       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9471       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9472
9473       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9474       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9475       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9476       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9477       if(sign) {
9478         pic16_emitpcode(POC_BTFSC, 
9479                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9480         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9481       }
9482       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9483       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9484       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9485       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9486     } else {
9487       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9488       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9489       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9490       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9491       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9492       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9493       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9494       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9495       if(sign) {
9496         pic16_emitpcode(POC_BTFSC, 
9497                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9498         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9499       }
9500       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9501       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9502
9503         
9504     }
9505
9506     break;
9507   case 7:
9508     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9509     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9510     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9511     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9512     if(sign) {
9513       emitSKPNC;
9514       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9515     } else 
9516       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9517   }
9518 }
9519
9520
9521 /*-----------------------------------------------------------------*/
9522 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9523 /*-----------------------------------------------------------------*/
9524 static void shiftLLeftOrResult (operand *left, int offl,
9525                                 operand *result, int offr, int shCount)
9526 {
9527     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9528
9529     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9530     /* shift left accumulator */
9531     AccLsh(shCount);
9532     /* or with result */
9533     /* back to result */
9534     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9535 }
9536
9537 /*-----------------------------------------------------------------*/
9538 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9539 /*-----------------------------------------------------------------*/
9540 static void shiftRLeftOrResult (operand *left, int offl,
9541                                 operand *result, int offr, int shCount)
9542 {
9543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544     
9545     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9546     /* shift right accumulator */
9547     AccRsh(shCount, 1);
9548     /* or with result */
9549     /* back to result */
9550     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9551 }
9552
9553 /*-----------------------------------------------------------------*/
9554 /* genlshOne - left shift a one byte quantity by known count       */
9555 /*-----------------------------------------------------------------*/
9556 static void genlshOne (operand *result, operand *left, int shCount)
9557 {       
9558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9559     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9560 }
9561
9562 /*-----------------------------------------------------------------*/
9563 /* genlshTwo - left shift two bytes by known amount != 0           */
9564 /*-----------------------------------------------------------------*/
9565 static void genlshTwo (operand *result,operand *left, int shCount)
9566 {
9567     int size;
9568     
9569     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9570     size = pic16_getDataSize(result);
9571
9572     /* if shCount >= 8 */
9573     if (shCount >= 8) {
9574         shCount -= 8 ;
9575
9576         if (size > 1){
9577             if (shCount)
9578                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9579             else 
9580                 movLeft2Result(left, LSB, result, MSB16);
9581         }
9582         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9583     }
9584
9585     /*  1 <= shCount <= 7 */
9586     else {  
9587         if(size == 1)
9588             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9589         else 
9590             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9591     }
9592 }
9593
9594 /*-----------------------------------------------------------------*/
9595 /* shiftLLong - shift left one long from left to result            */
9596 /* offr = LSB or MSB16                                             */
9597 /*-----------------------------------------------------------------*/
9598 static void shiftLLong (operand *left, operand *result, int offr )
9599 {
9600     int size = AOP_SIZE(result);
9601     int same = pic16_sameRegs(AOP(left),AOP(result));
9602         int i;
9603
9604     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9605
9606         if (same && (offr == MSB16)) { //shift one byte
9607                 for(i=size-1;i>=MSB16;i--) {
9608                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9609                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9610                 }
9611         } else {
9612                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9613         }
9614         
9615     if (size > LSB+offr ){
9616                 if (same) {
9617                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9618                 } else {
9619                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9620                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9621                 }
9622          }
9623
9624     if(size > MSB16+offr){
9625                 if (same) {
9626                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9627                 } else {
9628                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9629                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9630                 }
9631     }
9632
9633     if(size > MSB24+offr){
9634                 if (same) {
9635                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9636                 } else {
9637                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9638                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9639                 }
9640     }
9641
9642     if(size > MSB32+offr){
9643                 if (same) {
9644                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9645                 } else {
9646                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9647                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9648                 }
9649     }
9650     if(offr != LSB)
9651                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9652
9653 }
9654
9655 /*-----------------------------------------------------------------*/
9656 /* genlshFour - shift four byte by a known amount != 0             */
9657 /*-----------------------------------------------------------------*/
9658 static void genlshFour (operand *result, operand *left, int shCount)
9659 {
9660     int size;
9661
9662     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9663     size = AOP_SIZE(result);
9664
9665     /* if shifting more that 3 bytes */
9666     if (shCount >= 24 ) {
9667         shCount -= 24;
9668         if (shCount)
9669             /* lowest order of left goes to the highest
9670             order of the destination */
9671             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9672         else
9673             movLeft2Result(left, LSB, result, MSB32);
9674
9675                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9676                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9677                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9678
9679         return;
9680     }
9681
9682     /* more than two bytes */
9683     else if ( shCount >= 16 ) {
9684         /* lower order two bytes goes to higher order two bytes */
9685         shCount -= 16;
9686         /* if some more remaining */
9687         if (shCount)
9688             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9689         else {
9690             movLeft2Result(left, MSB16, result, MSB32);
9691             movLeft2Result(left, LSB, result, MSB24);
9692         }
9693                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9694                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9695         return;
9696     }    
9697
9698     /* if more than 1 byte */
9699     else if ( shCount >= 8 ) {
9700         /* lower order three bytes goes to higher order  three bytes */
9701         shCount -= 8;
9702         if(size == 2){
9703             if(shCount)
9704                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9705             else
9706                 movLeft2Result(left, LSB, result, MSB16);
9707         }
9708         else{   /* size = 4 */
9709             if(shCount == 0){
9710                 movLeft2Result(left, MSB24, result, MSB32);
9711                 movLeft2Result(left, MSB16, result, MSB24);
9712                 movLeft2Result(left, LSB, result, MSB16);
9713                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9714             }
9715             else if(shCount == 1)
9716                 shiftLLong(left, result, MSB16);
9717             else{
9718                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9719                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9720                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9721                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9722             }
9723         }
9724     }
9725
9726     /* 1 <= shCount <= 7 */
9727     else if(shCount <= 3)
9728     { 
9729         shiftLLong(left, result, LSB);
9730         while(--shCount >= 1)
9731             shiftLLong(result, result, LSB);
9732     }
9733     /* 3 <= shCount <= 7, optimize */
9734     else{
9735         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9736         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9737         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9738     }
9739 }
9740
9741 /*-----------------------------------------------------------------*/
9742 /* genLeftShiftLiteral - left shifting by known count              */
9743 /*-----------------------------------------------------------------*/
9744 void pic16_genLeftShiftLiteral (operand *left,
9745                                  operand *right,
9746                                  operand *result,
9747                                  iCode *ic)
9748 {    
9749     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9750     int size;
9751
9752     FENTRY;
9753     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9754     pic16_freeAsmop(right,NULL,ic,TRUE);
9755
9756     pic16_aopOp(left,ic,FALSE);
9757     pic16_aopOp(result,ic,FALSE);
9758
9759     size = getSize(operandType(result));
9760
9761 #if VIEW_SIZE
9762     pic16_emitcode("; shift left ","result %d, left %d",size,
9763              AOP_SIZE(left));
9764 #endif
9765
9766     /* I suppose that the left size >= result size */
9767     if(shCount == 0){
9768         while(size--){
9769             movLeft2Result(left, size, result, size);
9770         }
9771     }
9772
9773     else if(shCount >= (size * 8))
9774         while(size--)
9775             pic16_aopPut(AOP(result),zero,size);
9776     else{
9777         switch (size) {
9778             case 1:
9779                 genlshOne (result,left,shCount);
9780                 break;
9781
9782             case 2:
9783             case 3:
9784                 genlshTwo (result,left,shCount);
9785                 break;
9786
9787             case 4:
9788                 genlshFour (result,left,shCount);
9789                 break;
9790         }
9791     }
9792     pic16_freeAsmop(left,NULL,ic,TRUE);
9793     pic16_freeAsmop(result,NULL,ic,TRUE);
9794 }
9795
9796 /*-----------------------------------------------------------------*
9797  * genMultiAsm - repeat assembly instruction for size of register.
9798  * if endian == 1, then the high byte (i.e base address + size of 
9799  * register) is used first else the low byte is used first;
9800  *-----------------------------------------------------------------*/
9801 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9802 {
9803
9804   int offset = 0;
9805
9806   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9807
9808   if(!reg)
9809     return;
9810
9811   if(!endian) {
9812     endian = 1;
9813   } else {
9814     endian = -1;
9815     offset = size-1;
9816   }
9817
9818   while(size--) {
9819     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9820     offset += endian;
9821   }
9822
9823 }
9824
9825 #if !(USE_GENERIC_SIGNED_SHIFT)
9826 /*-----------------------------------------------------------------*/
9827 /* genLeftShift - generates code for left shifting                 */
9828 /*-----------------------------------------------------------------*/
9829 static void genLeftShift (iCode *ic)
9830 {
9831   operand *left,*right, *result;
9832   int size, offset;
9833 //  char *l;
9834   symbol *tlbl , *tlbl1;
9835   pCodeOp *pctemp;
9836
9837   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9838
9839   right = IC_RIGHT(ic);
9840   left  = IC_LEFT(ic);
9841   result = IC_RESULT(ic);
9842
9843   pic16_aopOp(right,ic,FALSE);
9844
9845   /* if the shift count is known then do it 
9846      as efficiently as possible */
9847   if (AOP_TYPE(right) == AOP_LIT) {
9848     pic16_genLeftShiftLiteral (left,right,result,ic);
9849     return ;
9850   }
9851
9852   /* shift count is unknown then we have to form
9853    * a loop. Get the loop count in WREG : Note: we take
9854    * only the lower order byte since shifting
9855    * more than 32 bits make no sense anyway, ( the
9856    * largest size of an object can be only 32 bits ) */
9857   
9858   pic16_aopOp(left,ic,FALSE);
9859   pic16_aopOp(result,ic,FALSE);
9860
9861   /* now move the left to the result if they are not the
9862    * same, and if size > 1,
9863    * and if right is not same to result (!!!) -- VR */
9864   if (!pic16_sameRegs(AOP(left),AOP(result))
9865       && (AOP_SIZE(result) > 1)) {
9866
9867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9868
9869     size = AOP_SIZE(result);
9870     offset=0;
9871     while (size--) {
9872
9873 #if 0
9874       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9875       if (*l == '@' && (IS_AOP_PREG(result))) {
9876
9877           pic16_emitcode("mov","a,%s",l);
9878           pic16_aopPut(AOP(result),"a",offset);
9879       } else
9880 #endif
9881       {
9882         /* we don't know if left is a literal or a register, take care -- VR */
9883         mov2f(AOP(result), AOP(left), offset);
9884       }
9885       offset++;
9886     }
9887   }
9888
9889   size = AOP_SIZE(result);
9890
9891   /* if it is only one byte then */
9892   if (size == 1) {
9893     if(optimized_for_speed) {
9894       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9895       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9896       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9897       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9898       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9899       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9900       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9901       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9902       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9903       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9904       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9905       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9906     } else {
9907
9908       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9909
9910       tlbl = newiTempLabel(NULL);
9911
9912 #if 1
9913       /* this is already done, why change it? */
9914       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9915                 mov2f(AOP(result), AOP(left), 0);
9916       }
9917 #endif
9918
9919       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9920       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9921       pic16_emitpLabel(tlbl->key);
9922       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9923       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9924       emitSKPC;
9925       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9926     }
9927     goto release ;
9928   }
9929     
9930   if (pic16_sameRegs(AOP(left),AOP(result))) {
9931
9932     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9933     
9934     tlbl = newiTempLabel(NULL);
9935     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9936     genMultiAsm(POC_RRCF, result, size,1);
9937     pic16_emitpLabel(tlbl->key);
9938     genMultiAsm(POC_RLCF, result, size,0);
9939     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9940     emitSKPC;
9941     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9942     goto release;
9943   }
9944
9945   //tlbl = newiTempLabel(NULL);
9946   //offset = 0 ;   
9947   //tlbl1 = newiTempLabel(NULL);
9948
9949   //reAdjustPreg(AOP(result));    
9950     
9951   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9952   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9953   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9954   //MOVA(l);
9955   //pic16_emitcode("add","a,acc");         
9956   //pic16_aopPut(AOP(result),"a",offset++);
9957   //while (--size) {
9958   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9959   //  MOVA(l);
9960   //  pic16_emitcode("rlc","a");         
9961   //  pic16_aopPut(AOP(result),"a",offset++);
9962   //}
9963   //reAdjustPreg(AOP(result));
9964
9965   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9966   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9967
9968
9969   tlbl = newiTempLabel(NULL);
9970   tlbl1= newiTempLabel(NULL);
9971
9972   size = AOP_SIZE(result);
9973   offset = 1;
9974
9975   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9976
9977   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9978
9979   /* offset should be 0, 1 or 3 */
9980   
9981   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9982   emitSKPNZ;
9983   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9984
9985   pic16_emitpcode(POC_MOVWF, pctemp);
9986
9987
9988   pic16_emitpLabel(tlbl->key);
9989
9990   emitCLRC;
9991   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9992   while(--size)
9993     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9994
9995   pic16_emitpcode(POC_DECFSZ,  pctemp);
9996   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9997   pic16_emitpLabel(tlbl1->key);
9998
9999   pic16_popReleaseTempReg(pctemp,1);
10000
10001
10002  release:
10003   pic16_freeAsmop (right,NULL,ic,TRUE);
10004   pic16_freeAsmop(left,NULL,ic,TRUE);
10005   pic16_freeAsmop(result,NULL,ic,TRUE);
10006 }
10007 #endif
10008
10009
10010 #if 0
10011 #error old code (left here for reference)
10012 /*-----------------------------------------------------------------*/
10013 /* genLeftShift - generates code for left shifting                 */
10014 /*-----------------------------------------------------------------*/
10015 static void genLeftShift (iCode *ic)
10016 {
10017   operand *left,*right, *result;
10018   int size, offset;
10019   char *l;
10020   symbol *tlbl , *tlbl1;
10021   pCodeOp *pctemp;
10022
10023   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10024
10025   right = IC_RIGHT(ic);
10026   left  = IC_LEFT(ic);
10027   result = IC_RESULT(ic);
10028
10029   pic16_aopOp(right,ic,FALSE);
10030
10031   /* if the shift count is known then do it 
10032      as efficiently as possible */
10033   if (AOP_TYPE(right) == AOP_LIT) {
10034     pic16_genLeftShiftLiteral (left,right,result,ic);
10035     return ;
10036   }
10037
10038   /* shift count is unknown then we have to form 
10039      a loop get the loop count in B : Note: we take
10040      only the lower order byte since shifting
10041      more that 32 bits make no sense anyway, ( the
10042      largest size of an object can be only 32 bits ) */  
10043
10044     
10045   pic16_aopOp(left,ic,FALSE);
10046   pic16_aopOp(result,ic,FALSE);
10047
10048   /* now move the left to the result if they are not the
10049      same */
10050   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10051       AOP_SIZE(result) > 1) {
10052
10053     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10054
10055     size = AOP_SIZE(result);
10056     offset=0;
10057     while (size--) {
10058       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10059       if (*l == '@' && (IS_AOP_PREG(result))) {
10060
10061         pic16_emitcode("mov","a,%s",l);
10062         pic16_aopPut(AOP(result),"a",offset);
10063       } else {
10064
10065         /* we don't know if left is a literal or a register, take care -- VR */
10066         mov2f(AOP(result), AOP(left), offset);
10067       }
10068       offset++;
10069     }
10070   }
10071
10072   size = AOP_SIZE(result);
10073
10074   /* if it is only one byte then */
10075   if (size == 1) {
10076     if(optimized_for_speed) {
10077       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10078       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10079       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10080       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10081       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10082       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10083       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10084       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10085       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10086       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10087       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10088       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10089     } else {
10090
10091       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10092
10093       tlbl = newiTempLabel(NULL);
10094       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10095                 mov2f(AOP(result), AOP(left), 0);
10096                 
10097 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10098 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10099       }
10100
10101       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10102       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10103       pic16_emitpLabel(tlbl->key);
10104       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10105       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10106       emitSKPC;
10107       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10108     }
10109     goto release ;
10110   }
10111     
10112   if (pic16_sameRegs(AOP(left),AOP(result))) {
10113
10114     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10115     
10116     tlbl = newiTempLabel(NULL);
10117     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10118     genMultiAsm(POC_RRCF, result, size,1);
10119     pic16_emitpLabel(tlbl->key);
10120     genMultiAsm(POC_RLCF, result, size,0);
10121     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10122     emitSKPC;
10123     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10124     goto release;
10125   }
10126
10127   //tlbl = newiTempLabel(NULL);
10128   //offset = 0 ;   
10129   //tlbl1 = newiTempLabel(NULL);
10130
10131   //reAdjustPreg(AOP(result));    
10132     
10133   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10134   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10135   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10136   //MOVA(l);
10137   //pic16_emitcode("add","a,acc");         
10138   //pic16_aopPut(AOP(result),"a",offset++);
10139   //while (--size) {
10140   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10141   //  MOVA(l);
10142   //  pic16_emitcode("rlc","a");         
10143   //  pic16_aopPut(AOP(result),"a",offset++);
10144   //}
10145   //reAdjustPreg(AOP(result));
10146
10147   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10148   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10149
10150
10151   tlbl = newiTempLabel(NULL);
10152   tlbl1= newiTempLabel(NULL);
10153
10154   size = AOP_SIZE(result);
10155   offset = 1;
10156
10157   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10158
10159   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10160
10161   /* offset should be 0, 1 or 3 */
10162   
10163   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10164   emitSKPNZ;
10165   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10166
10167   pic16_emitpcode(POC_MOVWF, pctemp);
10168
10169
10170   pic16_emitpLabel(tlbl->key);
10171
10172   emitCLRC;
10173   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10174   while(--size)
10175     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10176
10177   pic16_emitpcode(POC_DECFSZ,  pctemp);
10178   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10179   pic16_emitpLabel(tlbl1->key);
10180
10181   pic16_popReleaseTempReg(pctemp,1);
10182
10183
10184  release:
10185   pic16_freeAsmop (right,NULL,ic,TRUE);
10186   pic16_freeAsmop(left,NULL,ic,TRUE);
10187   pic16_freeAsmop(result,NULL,ic,TRUE);
10188 }
10189 #endif
10190
10191 /*-----------------------------------------------------------------*/
10192 /* genrshOne - right shift a one byte quantity by known count      */
10193 /*-----------------------------------------------------------------*/
10194 static void genrshOne (operand *result, operand *left,
10195                        int shCount, int sign)
10196 {
10197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10198     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10199 }
10200
10201 /*-----------------------------------------------------------------*/
10202 /* genrshTwo - right shift two bytes by known amount != 0          */
10203 /*-----------------------------------------------------------------*/
10204 static void genrshTwo (operand *result,operand *left,
10205                        int shCount, int sign)
10206 {
10207   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10208   /* if shCount >= 8 */
10209   if (shCount >= 8) {
10210     shCount -= 8 ;
10211     if (shCount)
10212       shiftR1Left2Result(left, MSB16, result, LSB,
10213                          shCount, sign);
10214     else
10215       movLeft2Result(left, MSB16, result, LSB);
10216
10217     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10218
10219     if(sign) {
10220       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10221       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10222     }
10223   }
10224
10225   /*  1 <= shCount <= 7 */
10226   else
10227     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10228 }
10229
10230 /*-----------------------------------------------------------------*/
10231 /* shiftRLong - shift right one long from left to result           */
10232 /* offl = LSB or MSB16                                             */
10233 /*-----------------------------------------------------------------*/
10234 static void shiftRLong (operand *left, int offl,
10235                         operand *result, int sign)
10236 {
10237     int size = AOP_SIZE(result);
10238     int same = pic16_sameRegs(AOP(left),AOP(result));
10239     int i;
10240     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10241
10242         if (same && (offl == MSB16)) { //shift one byte right
10243                 for(i=MSB16;i<size;i++) {
10244                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10245                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10246                 }
10247         }
10248
10249     if(sign)
10250                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10251         else
10252                 emitCLRC;
10253
10254         if (same) {
10255                 if (offl == LSB)
10256                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10257         } else {
10258         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10259         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10260         }
10261
10262     if(offl == MSB16) {
10263         /* add sign of "a" */
10264         pic16_addSign(result, MSB32, sign);
10265         }
10266
10267         if (same) {
10268         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10269         } else {
10270         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10271         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10272         }
10273         
10274         if (same) {
10275         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10276         } else {
10277         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10278         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10279         }
10280
10281         if (same) {
10282         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10283         } else {
10284         if(offl == LSB){
10285                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10286                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10287         }
10288         }
10289 }
10290
10291 /*-----------------------------------------------------------------*/
10292 /* genrshFour - shift four byte by a known amount != 0             */
10293 /*-----------------------------------------------------------------*/
10294 static void genrshFour (operand *result, operand *left,
10295                         int shCount, int sign)
10296 {
10297   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10298   /* if shifting more that 3 bytes */
10299   if(shCount >= 24 ) {
10300     shCount -= 24;
10301     if(shCount)
10302       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10303     else
10304       movLeft2Result(left, MSB32, result, LSB);
10305
10306     pic16_addSign(result, MSB16, sign);
10307   }
10308   else if(shCount >= 16){
10309     shCount -= 16;
10310     if(shCount)
10311       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10312     else{
10313       movLeft2Result(left, MSB24, result, LSB);
10314       movLeft2Result(left, MSB32, result, MSB16);
10315     }
10316     pic16_addSign(result, MSB24, sign);
10317   }
10318   else if(shCount >= 8){
10319     shCount -= 8;
10320     if(shCount == 1)
10321       shiftRLong(left, MSB16, result, sign);
10322     else if(shCount == 0){
10323       movLeft2Result(left, MSB16, result, LSB);
10324       movLeft2Result(left, MSB24, result, MSB16);
10325       movLeft2Result(left, MSB32, result, MSB24);
10326       pic16_addSign(result, MSB32, sign);
10327     }
10328     else{ //shcount >= 2
10329       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10330       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10331       /* the last shift is signed */
10332       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10333       pic16_addSign(result, MSB32, sign);
10334     }
10335   }
10336   else{   /* 1 <= shCount <= 7 */
10337     if(shCount <= 2){
10338       shiftRLong(left, LSB, result, sign);
10339       if(shCount == 2)
10340         shiftRLong(result, LSB, result, sign);
10341     }
10342     else{
10343       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10344       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10345       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10346     }
10347   }
10348 }
10349
10350 /*-----------------------------------------------------------------*/
10351 /* genRightShiftLiteral - right shifting by known count            */
10352 /*-----------------------------------------------------------------*/
10353 static void genRightShiftLiteral (operand *left,
10354                                   operand *right,
10355                                   operand *result,
10356                                   iCode *ic,
10357                                   int sign)
10358 {    
10359   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10360   int lsize,res_size;
10361
10362   pic16_freeAsmop(right,NULL,ic,TRUE);
10363
10364   pic16_aopOp(left,ic,FALSE);
10365   pic16_aopOp(result,ic,FALSE);
10366
10367   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10368
10369 #if VIEW_SIZE
10370   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10371                  AOP_SIZE(left));
10372 #endif
10373
10374   lsize = pic16_getDataSize(left);
10375   res_size = pic16_getDataSize(result);
10376   /* test the LEFT size !!! */
10377
10378   /* I suppose that the left size >= result size */
10379   if(shCount == 0){
10380     while(res_size--)
10381       movLeft2Result(left, lsize, result, res_size);
10382   }
10383
10384   else if(shCount >= (lsize * 8)){
10385
10386     if(res_size == 1) {
10387       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10388       if(sign) {
10389         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10390         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10391       }
10392     } else {
10393
10394       if(sign) {
10395         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10396         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10397         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10398         while(res_size--)
10399           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10400
10401       } else {
10402
10403         while(res_size--)
10404           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10405       }
10406     }
10407   } else {
10408
10409     switch (res_size) {
10410     case 1:
10411       genrshOne (result,left,shCount,sign);
10412       break;
10413
10414     case 2:
10415       genrshTwo (result,left,shCount,sign);
10416       break;
10417
10418     case 4:
10419       genrshFour (result,left,shCount,sign);
10420       break;
10421     default :
10422       break;
10423     }
10424
10425   }
10426
10427   pic16_freeAsmop(left,NULL,ic,TRUE);
10428   pic16_freeAsmop(result,NULL,ic,TRUE);
10429 }
10430
10431 #if !(USE_GENERIC_SIGNED_SHIFT)
10432 /*-----------------------------------------------------------------*/
10433 /* genSignedRightShift - right shift of signed number              */
10434 /*-----------------------------------------------------------------*/
10435 static void genSignedRightShift (iCode *ic)
10436 {
10437   operand *right, *left, *result;
10438   int size, offset;
10439   //  char *l;
10440   symbol *tlbl, *tlbl1 ;
10441   pCodeOp *pctemp;
10442
10443   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10444
10445   /* we do it the hard way put the shift count in b
10446      and loop thru preserving the sign */
10447   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10448
10449   right = IC_RIGHT(ic);
10450   left  = IC_LEFT(ic);
10451   result = IC_RESULT(ic);
10452
10453   pic16_aopOp(right,ic,FALSE);  
10454   pic16_aopOp(left,ic,FALSE);
10455   pic16_aopOp(result,ic,FALSE);
10456
10457
10458   if ( AOP_TYPE(right) == AOP_LIT) {
10459     genRightShiftLiteral (left,right,result,ic,1);
10460     return ;
10461   }
10462   /* shift count is unknown then we have to form 
10463      a loop get the loop count in B : Note: we take
10464      only the lower order byte since shifting
10465      more that 32 bits make no sense anyway, ( the
10466      largest size of an object can be only 32 bits ) */  
10467
10468   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10469   //pic16_emitcode("inc","b");
10470   //pic16_freeAsmop (right,NULL,ic,TRUE);
10471   //pic16_aopOp(left,ic,FALSE);
10472   //pic16_aopOp(result,ic,FALSE);
10473
10474   /* now move the left to the result if they are not the
10475      same */
10476   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10477       AOP_SIZE(result) > 1) {
10478
10479     size = AOP_SIZE(result);
10480     offset=0;
10481     while (size--) { 
10482       /*
10483         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10484         if (*l == '@' && IS_AOP_PREG(result)) {
10485
10486         pic16_emitcode("mov","a,%s",l);
10487         pic16_aopPut(AOP(result),"a",offset);
10488         } else
10489         pic16_aopPut(AOP(result),l,offset);
10490       */
10491       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10492       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10493
10494       offset++;
10495     }
10496   }
10497
10498   /* mov the highest order bit to OVR */    
10499   tlbl = newiTempLabel(NULL);
10500   tlbl1= newiTempLabel(NULL);
10501
10502   size = AOP_SIZE(result);
10503   offset = size - 1;
10504
10505   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10506
10507   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10508
10509   /* offset should be 0, 1 or 3 */
10510   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10511   emitSKPNZ;
10512   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10513
10514   pic16_emitpcode(POC_MOVWF, pctemp);
10515
10516
10517   pic16_emitpLabel(tlbl->key);
10518
10519   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10520   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10521
10522   while(--size) {
10523     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10524   }
10525
10526   pic16_emitpcode(POC_DECFSZ,  pctemp);
10527   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10528   pic16_emitpLabel(tlbl1->key);
10529
10530   pic16_popReleaseTempReg(pctemp,1);
10531 #if 0
10532   size = AOP_SIZE(result);
10533   offset = size - 1;
10534   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10535   pic16_emitcode("rlc","a");
10536   pic16_emitcode("mov","ov,c");
10537   /* if it is only one byte then */
10538   if (size == 1) {
10539     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10540     MOVA(l);
10541     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10542     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10543     pic16_emitcode("mov","c,ov");
10544     pic16_emitcode("rrc","a");
10545     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10546     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10547     pic16_aopPut(AOP(result),"a",0);
10548     goto release ;
10549   }
10550
10551   reAdjustPreg(AOP(result));
10552   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10553   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10554   pic16_emitcode("mov","c,ov");
10555   while (size--) {
10556     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10557     MOVA(l);
10558     pic16_emitcode("rrc","a");         
10559     pic16_aopPut(AOP(result),"a",offset--);
10560   }
10561   reAdjustPreg(AOP(result));
10562   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10563   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10564
10565  release:
10566 #endif
10567
10568   pic16_freeAsmop(left,NULL,ic,TRUE);
10569   pic16_freeAsmop(result,NULL,ic,TRUE);
10570   pic16_freeAsmop(right,NULL,ic,TRUE);
10571 }
10572 #endif
10573
10574 #if !(USE_GENERIC_SIGNED_SHIFT)
10575 #warning This implementation of genRightShift() is incomplete!
10576 /*-----------------------------------------------------------------*/
10577 /* genRightShift - generate code for right shifting                */
10578 /*-----------------------------------------------------------------*/
10579 static void genRightShift (iCode *ic)
10580 {
10581     operand *right, *left, *result;
10582     sym_link *letype ;
10583     int size, offset;
10584     char *l;
10585     symbol *tlbl, *tlbl1 ;
10586
10587     /* if signed then we do it the hard way preserve the
10588     sign bit moving it inwards */
10589     letype = getSpec(operandType(IC_LEFT(ic)));
10590     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10591
10592     if (!SPEC_USIGN(letype)) {
10593         genSignedRightShift (ic);
10594         return ;
10595     }
10596
10597     /* signed & unsigned types are treated the same : i.e. the
10598     signed is NOT propagated inwards : quoting from the
10599     ANSI - standard : "for E1 >> E2, is equivalent to division
10600     by 2**E2 if unsigned or if it has a non-negative value,
10601     otherwise the result is implementation defined ", MY definition
10602     is that the sign does not get propagated */
10603
10604     right = IC_RIGHT(ic);
10605     left  = IC_LEFT(ic);
10606     result = IC_RESULT(ic);
10607
10608     pic16_aopOp(right,ic,FALSE);
10609
10610     /* if the shift count is known then do it 
10611     as efficiently as possible */
10612     if (AOP_TYPE(right) == AOP_LIT) {
10613         genRightShiftLiteral (left,right,result,ic, 0);
10614         return ;
10615     }
10616
10617     /* shift count is unknown then we have to form 
10618     a loop get the loop count in B : Note: we take
10619     only the lower order byte since shifting
10620     more that 32 bits make no sense anyway, ( the
10621     largest size of an object can be only 32 bits ) */  
10622
10623     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10624     pic16_emitcode("inc","b");
10625     pic16_aopOp(left,ic,FALSE);
10626     pic16_aopOp(result,ic,FALSE);
10627
10628     /* now move the left to the result if they are not the
10629     same */
10630     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10631         AOP_SIZE(result) > 1) {
10632
10633         size = AOP_SIZE(result);
10634         offset=0;
10635         while (size--) {
10636             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10637             if (*l == '@' && IS_AOP_PREG(result)) {
10638
10639                 pic16_emitcode("mov","a,%s",l);
10640                 pic16_aopPut(AOP(result),"a",offset);
10641             } else
10642                 pic16_aopPut(AOP(result),l,offset);
10643             offset++;
10644         }
10645     }
10646
10647     tlbl = newiTempLabel(NULL);
10648     tlbl1= newiTempLabel(NULL);
10649     size = AOP_SIZE(result);
10650     offset = size - 1;
10651
10652     /* if it is only one byte then */
10653     if (size == 1) {
10654
10655       tlbl = newiTempLabel(NULL);
10656       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10657         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10658         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10659       }
10660
10661       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10662       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10663       pic16_emitpLabel(tlbl->key);
10664       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10665       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10666       emitSKPC;
10667       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10668
10669       goto release ;
10670     }
10671
10672     reAdjustPreg(AOP(result));
10673     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10674     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10675     CLRC;
10676     while (size--) {
10677         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10678         MOVA(l);
10679         pic16_emitcode("rrc","a");         
10680         pic16_aopPut(AOP(result),"a",offset--);
10681     }
10682     reAdjustPreg(AOP(result));
10683
10684     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10685     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10686
10687 release:
10688     pic16_freeAsmop(left,NULL,ic,TRUE);
10689     pic16_freeAsmop (right,NULL,ic,TRUE);
10690     pic16_freeAsmop(result,NULL,ic,TRUE);
10691 }
10692 #endif
10693
10694 #if (USE_GENERIC_SIGNED_SHIFT)
10695 /*-----------------------------------------------------------------*/
10696 /* genGenericShift - generates code for left or right shifting     */
10697 /*-----------------------------------------------------------------*/
10698 static void genGenericShift (iCode *ic, int isShiftLeft) {
10699   operand *left,*right, *result;
10700   int offset;
10701   int sign, signedCount;
10702   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10703   PIC_OPCODE pos_shift, neg_shift;
10704
10705   FENTRY;
10706
10707   right = IC_RIGHT(ic);
10708   left  = IC_LEFT(ic);
10709   result = IC_RESULT(ic);
10710
10711   pic16_aopOp(right,ic,FALSE);
10712   pic16_aopOp(left,ic,FALSE);
10713   pic16_aopOp(result,ic,FALSE);
10714
10715   sign = !SPEC_USIGN(operandType (left));
10716   signedCount = !SPEC_USIGN(operandType (right));
10717
10718   /* if the shift count is known then do it 
10719      as efficiently as possible */
10720   if (AOP_TYPE(right) == AOP_LIT) {
10721     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10722     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10723     // we should modify right->aopu.aop_lit here!
10724     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10725     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10726     if (isShiftLeft)
10727       pic16_genLeftShiftLiteral (left,right,result,ic);
10728     else
10729       genRightShiftLiteral (left,right,result,ic, sign);
10730
10731     goto release;
10732   } // if (right is literal)
10733
10734   /* shift count is unknown then we have to form a loop.
10735    * Note: we take only the lower order byte since shifting
10736    * more than 32 bits make no sense anyway, ( the
10737    * largest size of an object can be only 32 bits )
10738    * Note: we perform arithmetic shifts if the left operand is
10739    * signed and we do an (effective) right shift, i. e. we
10740    * shift in the sign bit from the left. */
10741    
10742   label_complete = newiTempLabel ( NULL );
10743   label_loop_pos = newiTempLabel ( NULL );
10744   label_loop_neg = NULL;
10745   label_negative = NULL;
10746   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10747   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10748
10749   if (signedCount) {
10750     // additional labels needed
10751     label_loop_neg = newiTempLabel ( NULL );
10752     label_negative = newiTempLabel ( NULL );
10753   } // if
10754
10755   // copy source to result -- this will effectively truncate the left operand to the size of result!
10756   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10757   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10758   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10759     mov2f (AOP(result),AOP(left), offset);
10760   } // for
10761
10762   // if result is longer than left, fill with zeros (or sign)
10763   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10764     if (sign && AOP_SIZE(left) > 0) {
10765       // shift signed operand -- fill with sign
10766       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10767       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10768       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10769       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10770         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10771       } // for
10772     } else {
10773       // shift unsigned operand -- fill result with zeros
10774       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10775         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10776       } // for
10777     }
10778   } // if (size mismatch)
10779
10780   pic16_mov2w (AOP(right), 0);
10781   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10782   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10783   
10784 #if 0
10785   // perform a shift by one (shift count is positive)
10786   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10787   // 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])
10788   pic16_emitpLabel (label_loop_pos->key);
10789   emitCLRC;
10790   if (sign && (pos_shift == POC_RRCF)) {
10791     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10792     emitSETC;
10793   } // if
10794   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10795   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10796   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10797 #else
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]+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])
10801   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10802   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10803   emitCLRC;
10804   pic16_emitpLabel (label_loop_pos->key);
10805   if (sign && (pos_shift == POC_RRCF)) {
10806     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10807     emitSETC;
10808   } // if
10809   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10810   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10811   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10812   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10813 #endif
10814
10815   if (signedCount) {
10816     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10817
10818     pic16_emitpLabel (label_negative->key);
10819     // perform a shift by -1 (shift count is negative)
10820     // 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)
10821     emitCLRC;
10822     pic16_emitpLabel (label_loop_neg->key);
10823     if (sign && (neg_shift == POC_RRCF)) {
10824       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10825       emitSETC;
10826     } // if
10827     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10828     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10829     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10830     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10831   } // if (signedCount)
10832
10833   pic16_emitpLabel (label_complete->key);
10834
10835 release:
10836   pic16_freeAsmop (right,NULL,ic,TRUE);
10837   pic16_freeAsmop(left,NULL,ic,TRUE);
10838   pic16_freeAsmop(result,NULL,ic,TRUE);
10839 }
10840
10841 static void genLeftShift (iCode *ic) {
10842   genGenericShift (ic, 1);
10843 }
10844
10845 static void genRightShift (iCode *ic) {
10846   genGenericShift (ic, 0);
10847 }
10848 #endif
10849
10850
10851 void pic16_loadFSR0(operand *op)
10852 {
10853         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10854 }
10855
10856 /*-----------------------------------------------------------------*/
10857 /* genUnpackBits - generates code for unpacking bits               */
10858 /*-----------------------------------------------------------------*/
10859 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10860 {    
10861   int shCnt ;
10862   int rlen = 0 ;
10863   sym_link *etype, *letype;
10864   int blen=0, bstr=0;
10865   int lbstr;
10866   int offset = 0 ;
10867
10868     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10869     etype = getSpec(operandType(result));
10870     letype = getSpec(operandType(left));
10871     
10872 //    if(IS_BITFIELD(etype)) {
10873       blen = SPEC_BLEN(etype);
10874       bstr = SPEC_BSTR(etype);
10875 //    }
10876
10877     lbstr = SPEC_BSTR( letype );
10878
10879 #if 1
10880     if((blen == 1) && (bstr < 8)) {
10881       /* it is a single bit, so use the appropriate bit instructions */
10882       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10883
10884       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10885       
10886       if((ptype == POINTER) && (result)) {
10887         /* workaround to reduce the extra lfsr instruction */
10888         pic16_emitpcode(POC_BTFSC,
10889               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10890       } else {
10891         pic16_emitpcode(POC_BTFSC,
10892               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10893       }
10894         
10895       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10896
10897       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10898       return;
10899     }
10900
10901 #endif
10902
10903         /* the following call to pic16_loadFSR0 is temporary until
10904          * optimization to handle single bit assignments is added
10905          * to the function. Until then use the old safe way! -- VR */
10906         pic16_loadFSR0( left );
10907  
10908         /* read the first byte  */
10909         switch (ptype) {
10910                 case POINTER:
10911                 case IPOINTER:
10912                 case PPOINTER:
10913                 case FPOINTER:
10914                 case GPOINTER:
10915                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10916                         break;
10917                 case CPOINTER:
10918                         pic16_emitcode("clr","a");
10919                         pic16_emitcode("movc","a","@a+dptr");
10920                         break;
10921         }
10922         
10923
10924         /* if we have bitdisplacement then it fits   */
10925         /* into this byte completely or if length is */
10926         /* less than a byte                          */
10927         if ((shCnt = SPEC_BSTR(etype)) || 
10928                 (SPEC_BLEN(etype) <= 8))  {
10929
10930                 /* shift right acc */
10931                 AccRsh(shCnt, 0);
10932
10933                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10934                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10935
10936 /* VR -- normally I would use the following, but since we use the hack,
10937  * to avoid the masking from AccRsh, why not mask it right now? */
10938
10939 /*
10940                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10941 */
10942
10943                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10944           return ;
10945         }
10946
10947
10948
10949         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10950         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10951         exit(-1);
10952
10953     /* bit field did not fit in a byte  */
10954     rlen = SPEC_BLEN(etype) - 8;
10955     pic16_aopPut(AOP(result),"a",offset++);
10956
10957     while (1)  {
10958
10959         switch (ptype) {
10960         case POINTER:
10961         case IPOINTER:
10962             pic16_emitcode("inc","%s",rname);
10963             pic16_emitcode("mov","a,@%s",rname);
10964             break;
10965             
10966         case PPOINTER:
10967             pic16_emitcode("inc","%s",rname);
10968             pic16_emitcode("movx","a,@%s",rname);
10969             break;
10970
10971         case FPOINTER:
10972             pic16_emitcode("inc","dptr");
10973             pic16_emitcode("movx","a,@dptr");
10974             break;
10975             
10976         case CPOINTER:
10977             pic16_emitcode("clr","a");
10978             pic16_emitcode("inc","dptr");
10979             pic16_emitcode("movc","a","@a+dptr");
10980             break;
10981             
10982         case GPOINTER:
10983             pic16_emitcode("inc","dptr");
10984             pic16_emitcode("lcall","__gptrget");
10985             break;
10986         }
10987
10988         rlen -= 8;            
10989         /* if we are done */
10990         if ( rlen <= 0 )
10991             break ;
10992         
10993         pic16_aopPut(AOP(result),"a",offset++);
10994                               
10995     }
10996     
10997     if (rlen) {
10998         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10999         pic16_aopPut(AOP(result),"a",offset);          
11000     }
11001     
11002     return ;
11003 }
11004
11005
11006 static void genDataPointerGet(operand *left,
11007                               operand *result,
11008                               iCode *ic)
11009 {
11010   int size, offset = 0, leoffset=0 ;
11011
11012         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11013         pic16_aopOp(result, ic, FALSE);
11014
11015         size = AOP_SIZE(result);
11016 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11017
11018
11019 #if 0
11020         /* The following tests may save a redudant movff instruction when
11021          * accessing unions */
11022          
11023         /* if they are the same */
11024         if (operandsEqu (left, result)) {
11025                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11026                 goto release;
11027         }
11028 #endif
11029
11030 #if 0
11031         /* if they are the same registers */
11032         if (pic16_sameRegs(AOP(left),AOP(result))) {
11033                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11034                 goto release;
11035         }
11036 #endif
11037
11038 #if 1
11039         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11040                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11041                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11042                 goto release;
11043         }
11044 #endif
11045
11046
11047 #if 0
11048         if ( AOP_TYPE(left) == AOP_PCODE) {
11049                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11050                                 AOP(left)->aopu.pcop->name,
11051                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11052                                 PCOR(AOP(left)->aopu.pcop)->instance:
11053                                 PCOI(AOP(left)->aopu.pcop)->offset);
11054         }
11055 #endif
11056
11057         if(AOP(left)->aopu.pcop->type == PO_DIR)
11058                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11059
11060         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11061
11062         while (size--) {
11063                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11064                 
11065                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11066                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11067                         pic16_mov2w(AOP(left), offset); // patch 8
11068                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11069                 } else {
11070                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11071                                 pic16_popGet(AOP(left), offset), //patch 8
11072                                 pic16_popGet(AOP(result), offset)));
11073                 }
11074
11075                 offset++;
11076                 leoffset++;
11077         }
11078
11079 release:
11080     pic16_freeAsmop(result,NULL,ic,TRUE);
11081 }
11082
11083
11084
11085 /*-----------------------------------------------------------------*/
11086 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11087 /*-----------------------------------------------------------------*/
11088 static void genNearPointerGet (operand *left, 
11089                                operand *result, 
11090                                iCode *ic)
11091 {
11092   asmop *aop = NULL;
11093   //regs *preg = NULL ;
11094   sym_link *rtype, *retype;
11095   sym_link *ltype = operandType(left);    
11096
11097     FENTRY;
11098     
11099     rtype = operandType(result);
11100     retype= getSpec(rtype);
11101     
11102     pic16_aopOp(left,ic,FALSE);
11103
11104 //    pic16_DumpOp("(left)",left);
11105 //    pic16_DumpOp("(result)",result);
11106
11107     /* if left is rematerialisable and
11108      * result is not bit variable type and
11109      * the left is pointer to data space i.e
11110      * lower 128 bytes of space */
11111     
11112     if (AOP_TYPE(left) == AOP_PCODE
11113       && !IS_BITFIELD(retype)
11114       && DCL_TYPE(ltype) == POINTER) {
11115
11116         genDataPointerGet (left,result,ic);
11117         pic16_freeAsmop(left, NULL, ic, TRUE);
11118         return ;
11119     }
11120     
11121     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11122     pic16_aopOp (result,ic,FALSE);
11123     
11124     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11125
11126 #if 1
11127     if(IS_BITFIELD( retype )
11128       && (SPEC_BLEN(operandType(result))==1)
11129     ) {
11130       iCode *nextic;
11131       pCodeOp *jop;
11132       int bitstrt, bytestrt;
11133
11134         /* if this is bitfield of size 1, see if we are checking the value
11135          * of a single bit in an if-statement,
11136          * if yes, then don't generate usual code, but execute the
11137          * genIfx directly -- VR */
11138
11139         nextic = ic->next;
11140
11141         /* CHECK: if next iCode is IFX
11142          * and current result operand is nextic's conditional operand
11143          * and current result operand live ranges ends at nextic's key number
11144          */
11145         if((nextic->op == IFX)
11146           && (result == IC_COND(nextic))
11147           && (OP_LIVETO(result) == nextic->seq)
11148           ) {
11149             /* everything is ok then */
11150             /* find a way to optimize the genIfx iCode */
11151
11152             bytestrt = SPEC_BSTR(operandType(result))/8;
11153             bitstrt = SPEC_BSTR(operandType(result))%8;
11154             
11155             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11156
11157             genIfxpCOpJump(nextic, jop);
11158             
11159             pic16_freeAsmop(left, NULL, ic, TRUE);
11160             pic16_freeAsmop(result, NULL, ic, TRUE);
11161             return;
11162         }
11163     }
11164 #endif
11165
11166
11167     /* if the value is already in a pointer register
11168      * then don't need anything more */
11169     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11170       /* otherwise get a free pointer register */
11171       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11172                 
11173       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11174       /* bitfields will be handled by genUnpackBits */
11175       if(!IS_BITFIELD(retype)) {
11176
11177         if(is_LitAOp( AOP(left) )) {
11178           pic16_loadFSR0( left );
11179         } else {
11180             // set up FSR0 with address from left
11181             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11182             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11183         }
11184       }
11185     }
11186
11187     /* if bitfield then unpack the bits */
11188     if (IS_BITFIELD(retype)) 
11189       genUnpackBits (result, left, NULL, POINTER);
11190     else {
11191       /* we have can just get the values */
11192       int size = AOP_SIZE(result);
11193       int offset = 0;   
11194         
11195       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11196
11197       /* fsr0 is loaded already -- VR */
11198 //      pic16_loadFSR0( left );
11199
11200 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11201 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11202       while(size--) {
11203         if(size) {
11204           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11205                 pic16_popGet(AOP(result), offset++)));
11206         } else {
11207           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11208                 pic16_popGet(AOP(result), offset++)));
11209         }
11210       }
11211 #if 0
11212 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11213 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11214       if(size)
11215         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11216 #endif
11217 /*
11218         while (size--) {
11219             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11220
11221                 pic16_emitcode("mov","a,@%s",rname);
11222                 pic16_aopPut(AOP(result),"a",offset);
11223             } else {
11224                 sprintf(buffer,"@%s",rname);
11225                 pic16_aopPut(AOP(result),buffer,offset);
11226             }
11227             offset++ ;
11228             if (size)
11229                 pic16_emitcode("inc","%s",rname);
11230         }
11231 */
11232     }
11233
11234     /* now some housekeeping stuff */
11235     if (aop) {
11236       /* we had to allocate for this iCode */
11237       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11238       pic16_freeAsmop(NULL,aop,ic,TRUE);
11239     } else { 
11240       /* we did not allocate which means left
11241        * already in a pointer register, then
11242        * if size > 0 && this could be used again
11243        * we have to point it back to where it 
11244        * belongs */
11245       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11246       if (AOP_SIZE(result) > 1
11247         && !OP_SYMBOL(left)->remat
11248         && ( OP_SYMBOL(left)->liveTo > ic->seq
11249             || ic->depth )) {
11250 //        int size = AOP_SIZE(result) - 1;
11251 //        while (size--)
11252 //          pic16_emitcode("dec","%s",rname);
11253         }
11254     }
11255
11256     /* done */
11257     pic16_freeAsmop(left,NULL,ic,TRUE);
11258     pic16_freeAsmop(result,NULL,ic,TRUE);
11259 }
11260
11261 /*-----------------------------------------------------------------*/
11262 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11263 /*-----------------------------------------------------------------*/
11264 static void genPagedPointerGet (operand *left, 
11265                                operand *result, 
11266                                iCode *ic)
11267 {
11268     asmop *aop = NULL;
11269     regs *preg = NULL ;
11270     char *rname ;
11271     sym_link *rtype, *retype;    
11272
11273     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11274
11275     rtype = operandType(result);
11276     retype= getSpec(rtype);
11277     
11278     pic16_aopOp(left,ic,FALSE);
11279
11280   /* if the value is already in a pointer register
11281        then don't need anything more */
11282     if (!AOP_INPREG(AOP(left))) {
11283         /* otherwise get a free pointer register */
11284         aop = newAsmop(0);
11285         preg = getFreePtr(ic,&aop,FALSE);
11286         pic16_emitcode("mov","%s,%s",
11287                 preg->name,
11288                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11289         rname = preg->name ;
11290     } else
11291         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11292     
11293     pic16_freeAsmop(left,NULL,ic,TRUE);
11294     pic16_aopOp (result,ic,FALSE);
11295
11296     /* if bitfield then unpack the bits */
11297     if (IS_BITFIELD(retype)) 
11298         genUnpackBits (result,left,rname,PPOINTER);
11299     else {
11300         /* we have can just get the values */
11301         int size = AOP_SIZE(result);
11302         int offset = 0 ;        
11303         
11304         while (size--) {
11305             
11306             pic16_emitcode("movx","a,@%s",rname);
11307             pic16_aopPut(AOP(result),"a",offset);
11308             
11309             offset++ ;
11310             
11311             if (size)
11312                 pic16_emitcode("inc","%s",rname);
11313         }
11314     }
11315
11316     /* now some housekeeping stuff */
11317     if (aop) {
11318         /* we had to allocate for this iCode */
11319         pic16_freeAsmop(NULL,aop,ic,TRUE);
11320     } else { 
11321         /* we did not allocate which means left
11322            already in a pointer register, then
11323            if size > 0 && this could be used again
11324            we have to point it back to where it 
11325            belongs */
11326         if (AOP_SIZE(result) > 1 &&
11327             !OP_SYMBOL(left)->remat &&
11328             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11329               ic->depth )) {
11330             int size = AOP_SIZE(result) - 1;
11331             while (size--)
11332                 pic16_emitcode("dec","%s",rname);
11333         }
11334     }
11335
11336     /* done */
11337     pic16_freeAsmop(result,NULL,ic,TRUE);
11338     
11339         
11340 }
11341
11342 /*-----------------------------------------------------------------*/
11343 /* genFarPointerGet - gget value from far space                    */
11344 /*-----------------------------------------------------------------*/
11345 static void genFarPointerGet (operand *left,
11346                               operand *result, iCode *ic)
11347 {
11348     int size, offset ;
11349     sym_link *retype = getSpec(operandType(result));
11350
11351     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11352
11353     pic16_aopOp(left,ic,FALSE);
11354
11355     /* if the operand is already in dptr 
11356     then we do nothing else we move the value to dptr */
11357     if (AOP_TYPE(left) != AOP_STR) {
11358         /* if this is remateriazable */
11359         if (AOP_TYPE(left) == AOP_IMMD)
11360             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11361         else { /* we need to get it byte by byte */
11362             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11363             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11364             if (options.model == MODEL_FLAT24)
11365             {
11366                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11367             }
11368         }
11369     }
11370     /* so dptr know contains the address */
11371     pic16_freeAsmop(left,NULL,ic,TRUE);
11372     pic16_aopOp(result,ic,FALSE);
11373
11374     /* if bit then unpack */
11375     if (IS_BITFIELD(retype)) 
11376         genUnpackBits(result,left,"dptr",FPOINTER);
11377     else {
11378         size = AOP_SIZE(result);
11379         offset = 0 ;
11380
11381         while (size--) {
11382             pic16_emitcode("movx","a,@dptr");
11383             pic16_aopPut(AOP(result),"a",offset++);
11384             if (size)
11385                 pic16_emitcode("inc","dptr");
11386         }
11387     }
11388
11389     pic16_freeAsmop(result,NULL,ic,TRUE);
11390 }
11391
11392 #if 0
11393 /*-----------------------------------------------------------------*/
11394 /* genCodePointerGet - get value from code space                  */
11395 /*-----------------------------------------------------------------*/
11396 static void genCodePointerGet (operand *left,
11397                                 operand *result, iCode *ic)
11398 {
11399     int size, offset ;
11400     sym_link *retype = getSpec(operandType(result));
11401
11402     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11403
11404     pic16_aopOp(left,ic,FALSE);
11405
11406     /* if the operand is already in dptr 
11407     then we do nothing else we move the value to dptr */
11408     if (AOP_TYPE(left) != AOP_STR) {
11409         /* if this is remateriazable */
11410         if (AOP_TYPE(left) == AOP_IMMD)
11411             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11412         else { /* we need to get it byte by byte */
11413             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11414             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11415             if (options.model == MODEL_FLAT24)
11416             {
11417                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11418             }
11419         }
11420     }
11421     /* so dptr know contains the address */
11422     pic16_freeAsmop(left,NULL,ic,TRUE);
11423     pic16_aopOp(result,ic,FALSE);
11424
11425     /* if bit then unpack */
11426     if (IS_BITFIELD(retype)) 
11427         genUnpackBits(result,left,"dptr",CPOINTER);
11428     else {
11429         size = AOP_SIZE(result);
11430         offset = 0 ;
11431
11432         while (size--) {
11433             pic16_emitcode("clr","a");
11434             pic16_emitcode("movc","a,@a+dptr");
11435             pic16_aopPut(AOP(result),"a",offset++);
11436             if (size)
11437                 pic16_emitcode("inc","dptr");
11438         }
11439     }
11440
11441     pic16_freeAsmop(result,NULL,ic,TRUE);
11442 }
11443 #endif
11444
11445 #if 0
11446 /*-----------------------------------------------------------------*/
11447 /* genGenPointerGet - gget value from generic pointer space        */
11448 /*-----------------------------------------------------------------*/
11449 static void genGenPointerGet (operand *left,
11450                               operand *result, iCode *ic)
11451 {
11452   int size, offset, lit;
11453   sym_link *retype = getSpec(operandType(result));
11454
11455         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11456         pic16_aopOp(left,ic,FALSE);
11457         pic16_aopOp(result,ic,FALSE);
11458         size = AOP_SIZE(result);
11459
11460         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11461
11462         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11463
11464                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11465                 // load FSR0 from immediate
11466                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11467
11468 //              pic16_loadFSR0( left );
11469
11470                 offset = 0;
11471                 while(size--) {
11472                         if(size) {
11473                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11474                         } else {
11475                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11476                         }
11477                         offset++;
11478                 }
11479                 goto release;
11480
11481         }
11482         else { /* we need to get it byte by byte */
11483                 // set up FSR0 with address from left
11484                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11485                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11486
11487                 offset = 0 ;
11488
11489                 while(size--) {
11490                         if(size) {
11491                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11492                         } else {
11493                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11494                         }
11495                         offset++;
11496                 }
11497                 goto release;
11498         }
11499
11500   /* if bit then unpack */
11501         if (IS_BITFIELD(retype)) 
11502                 genUnpackBits(result,left,"BAD",GPOINTER);
11503
11504         release:
11505         pic16_freeAsmop(left,NULL,ic,TRUE);
11506         pic16_freeAsmop(result,NULL,ic,TRUE);
11507
11508 }
11509 #endif
11510
11511
11512 /*-----------------------------------------------------------------*/
11513 /* genGenPointerGet - gget value from generic pointer space        */
11514 /*-----------------------------------------------------------------*/
11515 static void genGenPointerGet (operand *left,
11516                               operand *result, iCode *ic)
11517 {
11518   int size, offset, lit;
11519   sym_link *retype = getSpec(operandType(result));
11520   char fgptrget[32];
11521
11522     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11523     pic16_aopOp(left,ic,FALSE);
11524     pic16_aopOp(result,ic,FALSE);
11525     size = AOP_SIZE(result);
11526
11527     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11528
11529     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11530
11531       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11532       // load FSR0 from immediate
11533       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11534
11535       werror(W_POSSBUG2, __FILE__, __LINE__);
11536
11537       offset = 0;
11538       while(size--) {
11539         if(size) {
11540           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11541         } else {
11542           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11543         }
11544         offset++;
11545       }
11546
11547       goto release;
11548
11549     } else { /* we need to get it byte by byte */
11550
11551       /* set up WREG:PRODL:FSR0L with address from left */
11552       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11553       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11554       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11555       
11556       switch( size ) {
11557         case 1: strcpy(fgptrget, "__gptrget1"); break;
11558         case 2: strcpy(fgptrget, "__gptrget2"); break;
11559         case 3: strcpy(fgptrget, "__gptrget3"); break;
11560         case 4: strcpy(fgptrget, "__gptrget4"); break;
11561         default:
11562           werror(W_POSSBUG2, __FILE__, __LINE__);
11563           abort();
11564       }
11565       
11566       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11567       
11568       assignResultValue(result, 1);
11569       
11570       {
11571         symbol *sym;
11572
11573           sym = newSymbol( fgptrget, 0 );
11574           strcpy(sym->rname, fgptrget);
11575           checkAddSym(&externs, sym);
11576
11577 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11578       }
11579               
11580       goto release;
11581     }
11582
11583   /* if bit then unpack */
11584     if (IS_BITFIELD(retype)) 
11585       genUnpackBits(result,left,"BAD",GPOINTER);
11586
11587 release:
11588   pic16_freeAsmop(left,NULL,ic,TRUE);
11589   pic16_freeAsmop(result,NULL,ic,TRUE);
11590 }
11591
11592 /*-----------------------------------------------------------------*/
11593 /* genConstPointerGet - get value from const generic pointer space */
11594 /*-----------------------------------------------------------------*/
11595 static void genConstPointerGet (operand *left,
11596                                 operand *result, iCode *ic)
11597 {
11598   //sym_link *retype = getSpec(operandType(result));
11599   // symbol *albl = newiTempLabel(NULL);        // patch 15
11600   // symbol *blbl = newiTempLabel(NULL);        //
11601   // PIC_OPCODE poc;                            // patch 15
11602   int size;
11603   int offset = 0;
11604
11605   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11606   pic16_aopOp(left,ic,FALSE);
11607   pic16_aopOp(result,ic,TRUE);
11608   size = AOP_SIZE(result);
11609
11610   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11611
11612   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11613
11614   // set up table pointer
11615   if( (AOP_TYPE(left) == AOP_PCODE) 
11616       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11617           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11618     {
11619       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11620       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11621       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11622       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11623       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11624       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11625   } else {
11626     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11627     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11628     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11629   }
11630
11631   while(size--) {
11632     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11633     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11634     offset++;
11635   }
11636     
11637   pic16_freeAsmop(left,NULL,ic,TRUE);
11638   pic16_freeAsmop(result,NULL,ic,TRUE);
11639 }
11640
11641
11642 /*-----------------------------------------------------------------*/
11643 /* genPointerGet - generate code for pointer get                   */
11644 /*-----------------------------------------------------------------*/
11645 static void genPointerGet (iCode *ic)
11646 {
11647   operand *left, *result ;
11648   sym_link *type, *etype;
11649   int p_type;
11650
11651     FENTRY;
11652     
11653     left = IC_LEFT(ic);
11654     result = IC_RESULT(ic) ;
11655
11656     /* depending on the type of pointer we need to
11657     move it to the correct pointer register */
11658     type = operandType(left);
11659     etype = getSpec(type);
11660
11661 #if 0
11662     if (IS_PTR_CONST(type))
11663 #else
11664     if (IS_CODEPTR(type))
11665 #endif
11666       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11667
11668     /* if left is of type of pointer then it is simple */
11669     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11670       p_type = DCL_TYPE(type);
11671     else {
11672       /* we have to go by the storage class */
11673       p_type = PTR_TYPE(SPEC_OCLS(etype));
11674
11675       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11676
11677       if (SPEC_OCLS(etype)->codesp ) {
11678         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11679         //p_type = CPOINTER ;   
11680       } else
11681       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11682         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11683         /*p_type = FPOINTER ;*/ 
11684       } else
11685       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11686         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11687         /* p_type = PPOINTER; */
11688       } else
11689       if (SPEC_OCLS(etype) == idata ) {
11690         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11691         /* p_type = IPOINTER; */
11692       } else {
11693         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11694         /* p_type = POINTER ; */
11695       }
11696     }
11697
11698     /* now that we have the pointer type we assign
11699     the pointer values */
11700     switch (p_type) {
11701       case POINTER:     
11702       case IPOINTER:
11703         genNearPointerGet (left,result,ic);
11704         break;
11705
11706       case PPOINTER:
11707         genPagedPointerGet(left,result,ic);
11708         break;
11709
11710       case FPOINTER:
11711         genFarPointerGet (left,result,ic);
11712         break;
11713
11714       case CPOINTER:
11715         genConstPointerGet (left,result,ic);
11716         //pic16_emitcodePointerGet (left,result,ic);
11717         break;
11718
11719       case GPOINTER:
11720 #if 0
11721       if (IS_PTR_CONST(type))
11722         genConstPointerGet (left,result,ic);
11723       else
11724 #endif
11725         genGenPointerGet (left,result,ic);
11726       break;
11727
11728     default:
11729       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11730               "genPointerGet: illegal pointer type");
11731     
11732     }
11733 }
11734
11735 /*-----------------------------------------------------------------*/
11736 /* genPackBits - generates code for packed bit storage             */
11737 /*-----------------------------------------------------------------*/
11738 static void genPackBits (sym_link    *etype , operand *result,
11739                          operand *right ,
11740                          char *rname, int p_type)
11741 {
11742   int shCnt = 0 ;
11743   int offset = 0  ;
11744   int rLen = 0 ;
11745   int blen, bstr ;   
11746   sym_link *retype;
11747   char *l ;
11748
11749         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11750         blen = SPEC_BLEN(etype);
11751         bstr = SPEC_BSTR(etype);
11752
11753         retype = getSpec(operandType(right));
11754
11755         if(AOP_TYPE(right) == AOP_LIT) {
11756                 if((blen == 1) && (bstr < 8)) {
11757                   unsigned long lit;
11758                         /* it is a single bit, so use the appropriate bit instructions */
11759
11760                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11761
11762                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11763 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11764                         if((p_type == POINTER) && (result)) {
11765                                 /* workaround to reduce the extra lfsr instruction */
11766                                 if(lit) {
11767                                         pic16_emitpcode(POC_BSF,
11768                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11769                                 } else {
11770                                         pic16_emitpcode(POC_BCF,
11771                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11772                                 }
11773                         } else {
11774                                 pic16_loadFSR0( result );
11775                                 if(lit) {
11776                                         pic16_emitpcode(POC_BSF,
11777                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11778                                 } else {
11779                                         pic16_emitpcode(POC_BCF,
11780                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11781                                 }
11782                         }
11783         
11784                   return;
11785                 }
11786
11787                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11788                 offset++;
11789         } else
11790         if(IS_BITFIELD(retype) 
11791           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11792           && (blen == 1)) {
11793           int rblen, rbstr;
11794
11795             rblen = SPEC_BLEN( retype );
11796             rbstr = SPEC_BSTR( retype );
11797             
11798
11799             if(IS_BITFIELD(etype)) {
11800               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11801               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11802             } else {
11803               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11804             }
11805             
11806             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11807             
11808             if(IS_BITFIELD(etype)) {
11809               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11810             } else {
11811               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11812             }
11813
11814             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11815             
11816             return;
11817         } else
11818           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11819
11820         /* if the bit length is less than or   */
11821         /* it exactly fits a byte then         */
11822         if((shCnt=SPEC_BSTR(etype))
11823                 || SPEC_BLEN(etype) <= 8 )  {
11824                 int fsr0_setup = 0;
11825
11826                 if (blen != 8 || bstr != 0) {
11827                   // we need to combine the value with the old value
11828                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11829
11830                   /* shift left acc */
11831                   AccLsh(shCnt);
11832
11833                   /* using PRODH as a temporary register here */
11834                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11835
11836                   /* get old value */
11837                   switch (p_type) {
11838                         case FPOINTER:
11839                         case POINTER:
11840                                 pic16_loadFSR0( result );
11841                                 fsr0_setup = 1;
11842                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11843 //                              pic16_emitcode ("mov","b,a");
11844 //                              pic16_emitcode("mov","a,@%s",rname);
11845                                 break;
11846
11847                         case GPOINTER:
11848                                 if (AOP(result)->aopu.aop_reg[2]) {
11849                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11850                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11851                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11852                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11853                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11854                                   {
11855                                     symbol *sym;
11856                                     sym = newSymbol( "__gptrget1", 0 );
11857                                     strcpy(sym->rname, "__gptrget1");
11858                                     checkAddSym(&externs, sym);
11859                                   }
11860                                 } else {
11861                                   // data pointer (just 2 byte given)
11862                                   pic16_loadFSR0( result );
11863                                   fsr0_setup = 1;
11864                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11865                                 }
11866                                 
11867                                 // warnings will be emitted below
11868                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11869                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11870                                 break;
11871
11872                         default:
11873                                 assert (0 && "invalid pointer type specified");
11874                                 break;
11875                   }
11876 #if 1
11877                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11878                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11879                                         (unsigned char)(0xff >> (8-bstr))) ));
11880                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11881                 } // if (blen != 8 || bstr != 0)
11882
11883                 /* write new value back */
11884                 switch (p_type) {
11885                         case FPOINTER:
11886                         case POINTER:
11887                                 if (!fsr0_setup) pic16_loadFSR0( result );
11888                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11889                                 break;
11890
11891                         case GPOINTER:
11892                                 if (AOP(result)->aopu.aop_reg[2]) {
11893                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11894                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11895                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11896                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11897                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11898                                   pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11899                                   {
11900                                     symbol *sym;
11901                                     sym = newSymbol( "__gptrput1", 0 );
11902                                     strcpy(sym->rname, "__gptrput1");
11903                                     checkAddSym(&externs, sym);
11904                                   }
11905                                 } else {
11906                                   // data pointer (just 2 byte given)
11907                                   if (!fsr0_setup) pic16_loadFSR0( result );
11908                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11909                                 }
11910                                 
11911                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11912                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11913                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11914                                 break;
11915
11916                         default:
11917                                 assert (0 && "invalid pointer type specified");
11918                                 break;
11919                 }
11920 #endif
11921
11922           return;
11923         }
11924
11925
11926         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11927         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11928         exit(-1);
11929
11930
11931     /* if we r done */
11932     if ( SPEC_BLEN(etype) <= 8 )
11933         return ;
11934
11935     pic16_emitcode("inc","%s",rname);
11936     rLen = SPEC_BLEN(etype) ;     
11937
11938
11939
11940     /* now generate for lengths greater than one byte */
11941     while (1) {
11942
11943         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11944
11945         rLen -= 8 ;
11946         if (rLen <= 0 )
11947             break ;
11948
11949         switch (p_type) {
11950             case POINTER:
11951                 if (*l == '@') {
11952                     MOVA(l);
11953                     pic16_emitcode("mov","@%s,a",rname);
11954                 } else
11955                     pic16_emitcode("mov","@%s,%s",rname,l);
11956                 break;
11957
11958             case FPOINTER:
11959                 MOVA(l);
11960                 pic16_emitcode("movx","@dptr,a");
11961                 break;
11962
11963             case GPOINTER:
11964                 MOVA(l);
11965                 DEBUGpic16_emitcode(";lcall","__gptrput");
11966                 break;  
11967         }   
11968         pic16_emitcode ("inc","%s",rname);
11969     }
11970
11971     MOVA(l);
11972
11973     /* last last was not complete */
11974     if (rLen)   {
11975         /* save the byte & read byte */
11976         switch (p_type) {
11977             case POINTER:
11978                 pic16_emitcode ("mov","b,a");
11979                 pic16_emitcode("mov","a,@%s",rname);
11980                 break;
11981
11982             case FPOINTER:
11983                 pic16_emitcode ("mov","b,a");
11984                 pic16_emitcode("movx","a,@dptr");
11985                 break;
11986
11987             case GPOINTER:
11988                 pic16_emitcode ("push","b");
11989                 pic16_emitcode ("push","acc");
11990                 pic16_emitcode ("lcall","__gptrget");
11991                 pic16_emitcode ("pop","b");
11992                 break;
11993         }
11994
11995         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11996         pic16_emitcode ("orl","a,b");
11997     }
11998
11999     if (p_type == GPOINTER)
12000         pic16_emitcode("pop","b");
12001
12002     switch (p_type) {
12003
12004     case POINTER:
12005         pic16_emitcode("mov","@%s,a",rname);
12006         break;
12007         
12008     case FPOINTER:
12009         pic16_emitcode("movx","@dptr,a");
12010         break;
12011         
12012     case GPOINTER:
12013         DEBUGpic16_emitcode(";lcall","__gptrput");
12014         break;                  
12015     }
12016 }
12017 /*-----------------------------------------------------------------*/
12018 /* genDataPointerSet - remat pointer to data space                 */
12019 /*-----------------------------------------------------------------*/
12020 static void genDataPointerSet(operand *right,
12021                               operand *result,
12022                               iCode *ic)
12023 {
12024     int size, offset = 0, resoffset=0 ;
12025
12026     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12027     pic16_aopOp(right,ic,FALSE);
12028
12029     size = AOP_SIZE(right);
12030
12031 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12032
12033 #if 0
12034     if ( AOP_TYPE(result) == AOP_PCODE) {
12035       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12036               AOP(result)->aopu.pcop->name,
12037                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12038               PCOR(AOP(result)->aopu.pcop)->instance:
12039               PCOI(AOP(result)->aopu.pcop)->offset);
12040     }
12041 #endif
12042
12043         if(AOP(result)->aopu.pcop->type == PO_DIR)
12044                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12045
12046         while (size--) {
12047                 if (AOP_TYPE(right) == AOP_LIT) {
12048                   unsigned int lit;
12049
12050                     if(!IS_FLOAT(operandType( right )))
12051                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12052                     else {
12053                       union {
12054                         unsigned long lit_int;
12055                         float lit_float;
12056                       } info;
12057         
12058                         /* take care if literal is a float */
12059                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12060                         lit = info.lit_int;
12061                     }
12062
12063                     lit = lit >> (8*offset);
12064                     if(lit&0xff) {
12065                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12066                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12067                     } else {
12068                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12069                     }
12070                 } else {
12071                   pic16_mov2w(AOP(right), offset);
12072                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12073                 }
12074                 offset++;
12075                 resoffset++;
12076         }
12077
12078     pic16_freeAsmop(right,NULL,ic,TRUE);
12079 }
12080
12081
12082
12083 /*-----------------------------------------------------------------*/
12084 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12085 /*-----------------------------------------------------------------*/
12086 static void genNearPointerSet (operand *right,
12087                                operand *result, 
12088                                iCode *ic)
12089 {
12090   asmop *aop = NULL;
12091   char *l;
12092   sym_link *retype;
12093   sym_link *ptype = operandType(result);
12094   sym_link *resetype;
12095     
12096         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12097         retype= getSpec(operandType(right));
12098         resetype = getSpec(operandType(result));
12099   
12100         pic16_aopOp(result,ic,FALSE);
12101     
12102         /* if the result is rematerializable &
12103          * in data space & not a bit variable */
12104         
12105         /* and result is not a bit variable */
12106         if (AOP_TYPE(result) == AOP_PCODE
12107 //              && AOP_TYPE(result) == AOP_IMMD
12108                 && DCL_TYPE(ptype) == POINTER
12109                 && !IS_BITFIELD(retype)
12110                 && !IS_BITFIELD(resetype)) {
12111
12112                 genDataPointerSet (right,result,ic);
12113                 pic16_freeAsmop(result,NULL,ic,TRUE);
12114           return;
12115         }
12116
12117         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12118         pic16_aopOp(right,ic,FALSE);
12119         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12120
12121         /* if the value is already in a pointer register
12122          * then don't need anything more */
12123         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12124                 /* otherwise get a free pointer register */
12125                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12126
12127 //              if( (AOP_TYPE(result) == AOP_PCODE) 
12128 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12129 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12130                 if(is_LitAOp( AOP(result) ))
12131                 {
12132                   if(!IS_BITFIELD(resetype))
12133                         pic16_loadFSR0( result );  // patch 10
12134                 } else {
12135                   if(!IS_BITFIELD(resetype)) {
12136                         // set up FSR0 with address of result
12137                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12138                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12139                   }
12140                 }
12141
12142         }
12143 //      else
12144 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12145
12146         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12147
12148 //      pic16_loadFSR0( result );
12149
12150         /* if bitfield then unpack the bits */
12151         if (IS_BITFIELD(resetype)) {
12152                 genPackBits (resetype, result, right, NULL, POINTER);
12153         } else {
12154                 /* we have can just get the values */
12155           int size = AOP_SIZE(right);
12156           int offset = 0 ;    
12157
12158                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12159                 while (size--) {
12160                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12161                         if (*l == '@' ) {
12162                                 //MOVA(l);
12163                                 //pic16_emitcode("mov","@%s,a",rname);
12164                                 pic16_emitcode("movf","indf0,w ;1");
12165                         } else {
12166
12167                                 if (AOP_TYPE(right) == AOP_LIT) {
12168                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12169                                         if (size) {
12170                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12171                                         } else {
12172                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12173                                         }
12174                                 } else { // no literal
12175                                         if(size) {
12176                                                 pic16_emitpcode(POC_MOVFF,
12177                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12178                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12179                                         } else {
12180                                                 pic16_emitpcode(POC_MOVFF,
12181                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12182                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12183                                         }
12184                                 }
12185                         }
12186                         offset++;
12187                 }
12188         }
12189
12190         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12191         /* now some housekeeping stuff */
12192         if (aop) {
12193                 /* we had to allocate for this iCode */
12194                 pic16_freeAsmop(NULL,aop,ic,TRUE);
12195         } else { 
12196                 /* we did not allocate which means left
12197                  * already in a pointer register, then
12198                  * if size > 0 && this could be used again
12199                  * we have to point it back to where it 
12200                  * belongs */
12201                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12202                 if (AOP_SIZE(right) > 1
12203                         && !OP_SYMBOL(result)->remat
12204                         && ( OP_SYMBOL(result)->liveTo > ic->seq
12205                                 || ic->depth )) {
12206
12207                   int size = AOP_SIZE(right) - 1;
12208
12209                         while (size--)
12210                                 pic16_emitcode("decf","fsr0,f");
12211                         //pic16_emitcode("dec","%s",rname);
12212                 }
12213         }
12214
12215         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12216         /* done */
12217 //release:
12218         pic16_freeAsmop(right,NULL,ic,TRUE);
12219         pic16_freeAsmop(result,NULL,ic,TRUE);
12220 }
12221
12222 /*-----------------------------------------------------------------*/
12223 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12224 /*-----------------------------------------------------------------*/
12225 static void genPagedPointerSet (operand *right,
12226                                operand *result, 
12227                                iCode *ic)
12228 {
12229     asmop *aop = NULL;
12230     regs *preg = NULL ;
12231     char *rname , *l;
12232     sym_link *retype;
12233        
12234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12235
12236     retype= getSpec(operandType(right));
12237     
12238     pic16_aopOp(result,ic,FALSE);
12239     
12240     /* if the value is already in a pointer register
12241        then don't need anything more */
12242     if (!AOP_INPREG(AOP(result))) {
12243         /* otherwise get a free pointer register */
12244         aop = newAsmop(0);
12245         preg = getFreePtr(ic,&aop,FALSE);
12246         pic16_emitcode("mov","%s,%s",
12247                 preg->name,
12248                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12249         rname = preg->name ;
12250     } else
12251         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12252     
12253     pic16_freeAsmop(result,NULL,ic,TRUE);
12254     pic16_aopOp (right,ic,FALSE);
12255
12256     /* if bitfield then unpack the bits */
12257     if (IS_BITFIELD(retype)) 
12258         genPackBits (retype,result,right,rname,PPOINTER);
12259     else {
12260         /* we have can just get the values */
12261         int size = AOP_SIZE(right);
12262         int offset = 0 ;        
12263         
12264         while (size--) {
12265             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12266             
12267             MOVA(l);
12268             pic16_emitcode("movx","@%s,a",rname);
12269
12270             if (size)
12271                 pic16_emitcode("inc","%s",rname);
12272
12273             offset++;
12274         }
12275     }
12276     
12277     /* now some housekeeping stuff */
12278     if (aop) {
12279         /* we had to allocate for this iCode */
12280         pic16_freeAsmop(NULL,aop,ic,TRUE);
12281     } else { 
12282         /* we did not allocate which means left
12283            already in a pointer register, then
12284            if size > 0 && this could be used again
12285            we have to point it back to where it 
12286            belongs */
12287         if (AOP_SIZE(right) > 1 &&
12288             !OP_SYMBOL(result)->remat &&
12289             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12290               ic->depth )) {
12291             int size = AOP_SIZE(right) - 1;
12292             while (size--)
12293                 pic16_emitcode("dec","%s",rname);
12294         }
12295     }
12296
12297     /* done */
12298     pic16_freeAsmop(right,NULL,ic,TRUE);
12299     
12300         
12301 }
12302
12303 /*-----------------------------------------------------------------*/
12304 /* genFarPointerSet - set value from far space                     */
12305 /*-----------------------------------------------------------------*/
12306 static void genFarPointerSet (operand *right,
12307                               operand *result, iCode *ic)
12308 {
12309     int size, offset ;
12310     sym_link *retype = getSpec(operandType(right));
12311
12312     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12313     pic16_aopOp(result,ic,FALSE);
12314
12315     /* if the operand is already in dptr 
12316     then we do nothing else we move the value to dptr */
12317     if (AOP_TYPE(result) != AOP_STR) {
12318         /* if this is remateriazable */
12319         if (AOP_TYPE(result) == AOP_IMMD)
12320             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12321         else { /* we need to get it byte by byte */
12322             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12323             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12324             if (options.model == MODEL_FLAT24)
12325             {
12326                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12327             }
12328         }
12329     }
12330     /* so dptr know contains the address */
12331     pic16_freeAsmop(result,NULL,ic,TRUE);
12332     pic16_aopOp(right,ic,FALSE);
12333
12334     /* if bit then unpack */
12335     if (IS_BITFIELD(retype)) 
12336         genPackBits(retype,result,right,"dptr",FPOINTER);
12337     else {
12338         size = AOP_SIZE(right);
12339         offset = 0 ;
12340
12341         while (size--) {
12342             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12343             MOVA(l);
12344             pic16_emitcode("movx","@dptr,a");
12345             if (size)
12346                 pic16_emitcode("inc","dptr");
12347         }
12348     }
12349
12350     pic16_freeAsmop(right,NULL,ic,TRUE);
12351 }
12352
12353 /*-----------------------------------------------------------------*/
12354 /* genGenPointerSet - set value from generic pointer space         */
12355 /*-----------------------------------------------------------------*/
12356 #if 0
12357 static void genGenPointerSet (operand *right,
12358                               operand *result, iCode *ic)
12359 {
12360         int i, size, offset, lit;
12361         sym_link *retype = getSpec(operandType(right));
12362
12363         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12364
12365         pic16_aopOp(result,ic,FALSE);
12366         pic16_aopOp(right,ic,FALSE);
12367         size = AOP_SIZE(right);
12368         offset = 0;
12369
12370         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12371
12372         /* if the operand is already in dptr 
12373                 then we do nothing else we move the value to dptr */
12374         if (AOP_TYPE(result) != AOP_STR) {
12375                 /* if this is remateriazable */
12376                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12377                 // WARNING: anythig until "else" is untested!
12378                 if (AOP_TYPE(result) == AOP_IMMD) {
12379                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12380                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12381                         // load FSR0 from immediate
12382                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12383                         offset = 0;
12384                         while(size--) {
12385                                 if(size) {
12386                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12387                                 } else {
12388                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12389                                 }
12390                                 offset++;
12391                         }
12392                         goto release;
12393                 }
12394                 else { /* we need to get it byte by byte */
12395                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12396                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12397
12398                         // set up FSR0 with address of result
12399                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12400                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12401
12402                         /* hack hack! see if this the FSR. If so don't load W */
12403                         if(AOP_TYPE(right) != AOP_ACC) {
12404
12405                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12406
12407                                 if(AOP_TYPE(right) == AOP_LIT)
12408                                 {
12409                                         // copy literal
12410                                         // note: pic16_popGet handles sign extension
12411                                         for(i=0;i<size;i++) {
12412                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12413                                                 if(i < size-1)
12414                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12415                                                 else
12416                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12417                                         }
12418                                 } else {
12419                                         // copy regs
12420
12421                                         for(i=0;i<size;i++) {
12422                                                 if(i < size-1)
12423                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12424                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12425                                                 else
12426                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12427                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12428                                         }
12429                                 }
12430                                 goto release;
12431                         } 
12432                         // right = ACC
12433                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12434                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12435                         goto release;
12436         } // if (AOP_TYPE(result) != AOP_IMMD)
12437
12438         } // if (AOP_TYPE(result) != AOP_STR)
12439         /* so dptr know contains the address */
12440
12441
12442         /* if bit then unpack */
12443         if (IS_BITFIELD(retype)) 
12444                 genPackBits(retype,result,right,"dptr",GPOINTER);
12445         else {
12446                 size = AOP_SIZE(right);
12447                 offset = 0 ;
12448
12449                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12450
12451                 // set up FSR0 with address of result
12452                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12453                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12454         
12455                 while (size--) {
12456                         if (AOP_TYPE(right) == AOP_LIT) {
12457                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12458                                 if (size) {
12459                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12460                                 } else {
12461                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12462                                 }
12463                         } else { // no literal
12464                                 if(size) {
12465                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12466                                 } else {
12467                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12468                                 }
12469                         }
12470                         offset++;
12471                 }
12472         }
12473
12474         release:
12475         pic16_freeAsmop(right,NULL,ic,TRUE);
12476         pic16_freeAsmop(result,NULL,ic,TRUE);
12477 }
12478 #endif
12479
12480 static void genGenPointerSet (operand *right,
12481                               operand *result, iCode *ic)
12482 {
12483   int size;
12484   sym_link *retype = getSpec(operandType(right));
12485   char fgptrput[32];
12486
12487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12488
12489     pic16_aopOp(result,ic,FALSE);
12490     pic16_aopOp(right,ic,FALSE);
12491     size = AOP_SIZE(right);
12492
12493     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12494
12495
12496     /* if bit then unpack */
12497     if (IS_BITFIELD(retype)) {
12498 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12499       genPackBits(retype,result,right,"dptr",GPOINTER);
12500       goto release;
12501     }
12502
12503     size = AOP_SIZE(right);
12504
12505     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12506
12507
12508
12509     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12510
12511     /* value of right+0 is placed on stack, which will be retrieved
12512      * by the support function this restoring the stack. The important
12513      * thing is that there is no need to manually restore stack pointer
12514      * here */
12515     pushaop(AOP(right), 0);
12516 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12517     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12518     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12519     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12520     
12521     /* load address to write to in WREG:FSR0H:FSR0L */
12522     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12523                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12524     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12525                                 pic16_popCopyReg(&pic16_pc_prodl)));
12526     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12527     
12528
12529     /* put code here */
12530     switch (size) {
12531       case 1: strcpy(fgptrput, "__gptrput1"); break;
12532       case 2: strcpy(fgptrput, "__gptrput2"); break;
12533       case 3: strcpy(fgptrput, "__gptrput3"); break;
12534       case 4: strcpy(fgptrput, "__gptrput4"); break;
12535       default:
12536         werror(W_POSSBUG2, __FILE__, __LINE__);
12537         abort();
12538     }
12539     
12540     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12541     
12542     {
12543       symbol *sym;
12544                   
12545         sym = newSymbol( fgptrput, 0 );
12546         strcpy(sym->rname, fgptrput);
12547         checkAddSym(&externs, sym);
12548     }
12549
12550 release:
12551     pic16_freeAsmop(right,NULL,ic,TRUE);
12552     pic16_freeAsmop(result,NULL,ic,TRUE);
12553 }
12554
12555 /*-----------------------------------------------------------------*/
12556 /* genPointerSet - stores the value into a pointer location        */
12557 /*-----------------------------------------------------------------*/
12558 static void genPointerSet (iCode *ic)
12559 {    
12560   operand *right, *result ;
12561   sym_link *type, *etype;
12562   int p_type;
12563
12564     FENTRY;
12565
12566     right = IC_RIGHT(ic);
12567     result = IC_RESULT(ic) ;
12568
12569     /* depending on the type of pointer we need to
12570     move it to the correct pointer register */
12571     type = operandType(result);
12572     etype = getSpec(type);
12573     /* if left is of type of pointer then it is simple */
12574     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12575         p_type = DCL_TYPE(type);
12576     }
12577     else {
12578         /* we have to go by the storage class */
12579         p_type = PTR_TYPE(SPEC_OCLS(etype));
12580
12581 /*      if (SPEC_OCLS(etype)->codesp ) { */
12582 /*          p_type = CPOINTER ;  */
12583 /*      } */
12584 /*      else */
12585 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12586 /*              p_type = FPOINTER ; */
12587 /*          else */
12588 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12589 /*                  p_type = PPOINTER ; */
12590 /*              else */
12591 /*                  if (SPEC_OCLS(etype) == idata ) */
12592 /*                      p_type = IPOINTER ; */
12593 /*                  else */
12594 /*                      p_type = POINTER ; */
12595     }
12596
12597     /* now that we have the pointer type we assign
12598     the pointer values */
12599     switch (p_type) {
12600       case POINTER:
12601       case IPOINTER:
12602         genNearPointerSet (right,result,ic);
12603         break;
12604
12605       case PPOINTER:
12606         genPagedPointerSet (right,result,ic);
12607         break;
12608
12609       case FPOINTER:
12610         genFarPointerSet (right,result,ic);
12611         break;
12612         
12613       case GPOINTER:
12614         genGenPointerSet (right,result,ic);
12615         break;
12616
12617       default:
12618         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12619           "genPointerSet: illegal pointer type");
12620     }
12621 }
12622
12623 /*-----------------------------------------------------------------*/
12624 /* genIfx - generate code for Ifx statement                        */
12625 /*-----------------------------------------------------------------*/
12626 static void genIfx (iCode *ic, iCode *popIc)
12627 {
12628   operand *cond = IC_COND(ic);
12629   int isbit =0;
12630
12631     FENTRY;
12632
12633     pic16_aopOp(cond,ic,FALSE);
12634
12635     /* get the value into acc */
12636     if (AOP_TYPE(cond) != AOP_CRY)
12637       pic16_toBoolean(cond);
12638     else
12639       isbit = 1;
12640     /* the result is now in the accumulator */
12641     pic16_freeAsmop(cond,NULL,ic,TRUE);
12642
12643     /* if there was something to be popped then do it */
12644     if (popIc)
12645       genIpop(popIc);
12646
12647     /* if the condition is  a bit variable */
12648     if (isbit && IS_ITEMP(cond) && 
12649         SPIL_LOC(cond)) {
12650       genIfxJump(ic,"c");
12651       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12652     } else {
12653       if (isbit && !IS_ITEMP(cond))
12654         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12655         else
12656         genIfxJump(ic,"a");
12657     }
12658     ic->generated = 1;
12659 }
12660
12661 /*-----------------------------------------------------------------*/
12662 /* genAddrOf - generates code for address of                       */
12663 /*-----------------------------------------------------------------*/
12664 static void genAddrOf (iCode *ic)
12665 {
12666   operand *result, *left;
12667   int size;
12668   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12669   pCodeOp *pcop0, *pcop1, *pcop2;
12670
12671     FENTRY;
12672
12673     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12674
12675     sym = OP_SYMBOL( IC_LEFT(ic) );
12676     
12677     if(sym->onStack) {
12678       /* get address of symbol on stack */
12679       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12680 #if 0
12681       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12682                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12683 #endif
12684
12685       // operands on stack are accessible via "FSR2 + index" with index
12686       // starting at 2 for arguments and growing from 0 downwards for
12687       // local variables (index == 0 is not assigned so we add one here)
12688       {
12689         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12690         if (soffs <= 0) {
12691           assert (soffs < 0);
12692           soffs++;
12693         } // if
12694         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12695         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12696         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12697         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12698         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12699         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12700         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12701       }
12702
12703       goto release;
12704     }
12705         
12706 //      if(pic16_debug_verbose) {
12707 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12708 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12709 //      }
12710         
12711     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12712     size = AOP_SIZE(IC_RESULT(ic));
12713
12714     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12715     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12716     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12717         
12718     if (size == 3) {
12719       pic16_emitpcode(POC_MOVLW, pcop0);
12720       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12721       pic16_emitpcode(POC_MOVLW, pcop1);
12722       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12723       pic16_emitpcode(POC_MOVLW, pcop2);
12724       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12725     } else
12726     if (size == 2) {
12727       pic16_emitpcode(POC_MOVLW, pcop0);
12728       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12729       pic16_emitpcode(POC_MOVLW, pcop1);
12730     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12731     } else {
12732       pic16_emitpcode(POC_MOVLW, pcop0);
12733       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12734     }
12735
12736     pic16_freeAsmop(left, NULL, ic, FALSE);
12737 release:
12738     pic16_freeAsmop(result,NULL,ic,TRUE);
12739 }
12740
12741
12742 #if 0
12743 /*-----------------------------------------------------------------*/
12744 /* genFarFarAssign - assignment when both are in far space         */
12745 /*-----------------------------------------------------------------*/
12746 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12747 {
12748     int size = AOP_SIZE(right);
12749     int offset = 0;
12750     char *l ;
12751     /* first push the right side on to the stack */
12752     while (size--) {
12753         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12754         MOVA(l);
12755         pic16_emitcode ("push","acc");
12756     }
12757     
12758     pic16_freeAsmop(right,NULL,ic,FALSE);
12759     /* now assign DPTR to result */
12760     pic16_aopOp(result,ic,FALSE);
12761     size = AOP_SIZE(result);
12762     while (size--) {
12763         pic16_emitcode ("pop","acc");
12764         pic16_aopPut(AOP(result),"a",--offset);
12765     }
12766     pic16_freeAsmop(result,NULL,ic,FALSE);
12767         
12768 }
12769 #endif
12770
12771 /*-----------------------------------------------------------------*/
12772 /* genAssign - generate code for assignment                        */
12773 /*-----------------------------------------------------------------*/
12774 static void genAssign (iCode *ic)
12775 {
12776   operand *result, *right;
12777   int size, offset,know_W;
12778   unsigned long lit = 0L;
12779
12780   result = IC_RESULT(ic);
12781   right  = IC_RIGHT(ic) ;
12782
12783   FENTRY;
12784   
12785   /* if they are the same */
12786   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12787     return ;
12788
12789   /* reversed order operands are aopOp'ed so that result operand
12790    * is effective in case right is a stack symbol. This maneauver
12791    * allows to use the _G.resDirect flag later */
12792   pic16_aopOp(result,ic,TRUE);
12793   pic16_aopOp(right,ic,FALSE);
12794
12795   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12796
12797   /* if they are the same registers */
12798   if (pic16_sameRegs(AOP(right),AOP(result)))
12799     goto release;
12800
12801   /* if the result is a bit */
12802   if (AOP_TYPE(result) == AOP_CRY) {
12803     /* if the right size is a literal then
12804        we know what the value is */
12805     if (AOP_TYPE(right) == AOP_LIT) {
12806           
12807       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12808                   pic16_popGet(AOP(result),0));
12809
12810       if (((int) operandLitValue(right))) 
12811         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12812                        AOP(result)->aopu.aop_dir,
12813                        AOP(result)->aopu.aop_dir);
12814       else
12815         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12816                        AOP(result)->aopu.aop_dir,
12817                        AOP(result)->aopu.aop_dir);
12818       goto release;
12819     }
12820
12821     /* the right is also a bit variable */
12822     if (AOP_TYPE(right) == AOP_CRY) {
12823       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12824       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12825       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12826
12827       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12828                      AOP(result)->aopu.aop_dir,
12829                      AOP(result)->aopu.aop_dir);
12830       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12831                      AOP(right)->aopu.aop_dir,
12832                      AOP(right)->aopu.aop_dir);
12833       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12834                      AOP(result)->aopu.aop_dir,
12835                      AOP(result)->aopu.aop_dir);
12836       goto release ;
12837     }
12838
12839     /* we need to or */
12840     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12841     pic16_toBoolean(right);
12842     emitSKPZ;
12843     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12844     //pic16_aopPut(AOP(result),"a",0);
12845     goto release ;
12846   }
12847
12848   /* bit variables done */
12849   /* general case */
12850   size = AOP_SIZE(result);
12851   offset = 0 ;
12852
12853   if(AOP_TYPE(right) == AOP_LIT) {
12854         if(!IS_FLOAT(operandType( right )))
12855                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12856         else {
12857            union {
12858               unsigned long lit_int;
12859               float lit_float;
12860             } info;
12861         
12862                 /* take care if literal is a float */
12863                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12864                 lit = info.lit_int;
12865         }
12866   }
12867
12868 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12869 //                      sizeof(unsigned long int), sizeof(float));
12870
12871
12872   if (AOP_TYPE(right) == AOP_REG) {
12873     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12874     while (size--) {
12875       
12876       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12877     } // while
12878     goto release;
12879   }
12880
12881   if(AOP_TYPE(right) != AOP_LIT
12882         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12883         && !IS_FUNC(OP_SYM_TYPE(right))
12884         ) {
12885         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12886         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12887
12888         // set up table pointer
12889         if(is_LitOp(right)) {
12890 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12891                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12892                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12893                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12894                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12895                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12896                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12897         } else {
12898 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12899                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12900                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12901                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12902                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12903                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12904                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12905         }
12906
12907         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12908         while(size--) {
12909                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12910                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12911                         pic16_popGet(AOP(result),offset)));
12912                 offset++;
12913         }
12914
12915         size = getSize(OP_SYM_ETYPE(right));
12916         if(AOP_SIZE(result) > size) {
12917                 size = AOP_SIZE(result) - size;
12918                 while(size--) {
12919                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12920                         offset++;
12921                 }
12922         }
12923         goto release;
12924   }
12925
12926
12927
12928 #if 0
12929 /* VR - What is this?! */
12930   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12931     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12932     if(aopIdx(AOP(result),0) == 4) {
12933
12934       /* this is a workaround to save value of right into wreg too,
12935        * value of wreg is going to be used later */
12936       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12937       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12938       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12939       goto release;
12940     } else
12941 //      assert(0);
12942       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12943   }
12944 #endif
12945
12946   know_W=-1;
12947   while (size--) {
12948   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12949     if(AOP_TYPE(right) == AOP_LIT) {
12950       if(lit&0xff) {
12951         if(know_W != (lit&0xff))
12952           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12953         know_W = lit&0xff;
12954         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12955       } else
12956         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12957
12958       lit >>= 8;
12959
12960     } else if (AOP_TYPE(right) == AOP_CRY) {
12961       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12962       if(offset == 0) {
12963         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12964         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12965         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12966       }
12967     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12968         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12969         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12970     } else {
12971       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12972
12973       if(!_G.resDirect)         /* use this aopForSym feature */
12974         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12975     }
12976             
12977     offset++;
12978   }
12979   
12980  release:
12981   pic16_freeAsmop (right,NULL,ic,FALSE);
12982   pic16_freeAsmop (result,NULL,ic,TRUE);
12983 }   
12984
12985 /*-----------------------------------------------------------------*/
12986 /* genJumpTab - generates code for jump table                       */
12987 /*-----------------------------------------------------------------*/
12988 static void genJumpTab (iCode *ic)
12989 {
12990   symbol *jtab;
12991   char *l;
12992   pCodeOp *jt_offs;
12993   pCodeOp *jt_offs_hi;
12994   pCodeOp *jt_label;
12995
12996     FENTRY;
12997
12998     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12999     /* get the condition into accumulator */
13000     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
13001     MOVA(l);
13002     /* multiply by three */
13003     pic16_emitcode("add","a,acc");
13004     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
13005
13006     jtab = newiTempLabel(NULL);
13007     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
13008     pic16_emitcode("jmp","@a+dptr");
13009     pic16_emitcode("","%05d_DS_:",jtab->key+100);
13010
13011 #if 0
13012     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
13013     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
13014     emitSKPNC;
13015     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
13016     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
13017     pic16_emitpLabel(jtab->key);
13018
13019 #else
13020
13021     jt_offs = pic16_popGetTempReg(0);
13022     jt_offs_hi = pic16_popGetTempReg(1);
13023     jt_label = pic16_popGetLabel (jtab->key);
13024     //fprintf (stderr, "Creating jump table...\n");
13025
13026     // calculate offset into jump table (idx * sizeof (GOTO))
13027     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
13028     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13029     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13030     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13031     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
13032     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13033     pic16_emitpcode(POC_MOVWF , jt_offs);
13034
13035     // prepare PCLATx (set to first entry in jump table)
13036     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13037     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13038     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13039     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13040     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13041
13042     // set PCLATx to selected entry (new PCL is stored in jt_offs)
13043     pic16_emitpcode(POC_ADDWF , jt_offs);
13044     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13045     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13046     emitSKPNC;
13047     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
13048
13049     // release temporaries and prepare jump into table (new PCL --> WREG)
13050     pic16_emitpcode(POC_MOVFW , jt_offs);
13051     pic16_popReleaseTempReg (jt_offs_hi, 1);
13052     pic16_popReleaseTempReg (jt_offs, 0);
13053
13054     // jump into the table
13055     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13056
13057     pic16_emitpLabelFORCE(jtab->key);
13058
13059 #endif
13060     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13061
13062     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13063     /* now generate the jump labels */
13064     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13065          jtab = setNextItem(IC_JTLABELS(ic))) {
13066 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13067         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13068         
13069     }
13070     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13071
13072 }
13073
13074 /*-----------------------------------------------------------------*/
13075 /* genMixedOperation - gen code for operators between mixed types  */
13076 /*-----------------------------------------------------------------*/
13077 /*
13078   TSD - Written for the PIC port - but this unfortunately is buggy.
13079   This routine is good in that it is able to efficiently promote 
13080   types to different (larger) sizes. Unfortunately, the temporary
13081   variables that are optimized out by this routine are sometimes
13082   used in other places. So until I know how to really parse the 
13083   iCode tree, I'm going to not be using this routine :(.
13084 */
13085 static int genMixedOperation (iCode *ic)
13086 {
13087 #if 0
13088   operand *result = IC_RESULT(ic);
13089   sym_link *ctype = operandType(IC_LEFT(ic));
13090   operand *right = IC_RIGHT(ic);
13091   int ret = 0;
13092   int big,small;
13093   int offset;
13094
13095   iCode *nextic;
13096   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13097
13098   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13099
13100   nextic = ic->next;
13101   if(!nextic)
13102     return 0;
13103
13104   nextright = IC_RIGHT(nextic);
13105   nextleft  = IC_LEFT(nextic);
13106   nextresult = IC_RESULT(nextic);
13107
13108   pic16_aopOp(right,ic,FALSE);
13109   pic16_aopOp(result,ic,FALSE);
13110   pic16_aopOp(nextright,  nextic, FALSE);
13111   pic16_aopOp(nextleft,   nextic, FALSE);
13112   pic16_aopOp(nextresult, nextic, FALSE);
13113
13114   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13115
13116     operand *t = right;
13117     right = nextright;
13118     nextright = t; 
13119
13120     pic16_emitcode(";remove right +","");
13121
13122   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13123 /*
13124     operand *t = right;
13125     right = nextleft;
13126     nextleft = t; 
13127 */
13128     pic16_emitcode(";remove left +","");
13129   } else
13130     return 0;
13131
13132   big = AOP_SIZE(nextleft);
13133   small = AOP_SIZE(nextright);
13134
13135   switch(nextic->op) {
13136
13137   case '+':
13138     pic16_emitcode(";optimize a +","");
13139     /* if unsigned or not an integral type */
13140     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13141       pic16_emitcode(";add a bit to something","");
13142     } else {
13143
13144       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13145
13146       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13147         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13148         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13149       } else
13150         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13151
13152       offset = 0;
13153       while(--big) {
13154
13155         offset++;
13156
13157         if(--small) {
13158           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13159             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13160             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13161           }
13162
13163           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13164           emitSKPNC;
13165           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13166                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13167                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13168           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13169           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13170
13171         } else {
13172           pic16_emitcode("rlf","known_zero,w");
13173
13174           /*
13175             if right is signed
13176               btfsc  right,7
13177                addlw ff
13178           */
13179           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13180             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13181             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13182           } else {
13183             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13184           }
13185         }
13186       }
13187       ret = 1;
13188     }
13189   }
13190   ret = 1;
13191
13192 release:
13193   pic16_freeAsmop(right,NULL,ic,TRUE);
13194   pic16_freeAsmop(result,NULL,ic,TRUE);
13195   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13196   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13197   if(ret)
13198     nextic->generated = 1;
13199
13200   return ret;
13201 #else
13202   return 0;
13203 #endif
13204 }
13205 /*-----------------------------------------------------------------*/
13206 /* genCast - gen code for casting                                  */
13207 /*-----------------------------------------------------------------*/
13208 static void genCast (iCode *ic)
13209 {
13210   operand *result = IC_RESULT(ic);
13211   sym_link *ctype = operandType(IC_LEFT(ic));
13212   sym_link *rtype = operandType(IC_RIGHT(ic));
13213   sym_link *restype = operandType(IC_RESULT(ic));
13214   operand *right = IC_RIGHT(ic);
13215   int size, offset ;
13216
13217
13218     FENTRY;
13219
13220         /* if they are equivalent then do nothing */
13221 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13222 //              return ;
13223
13224         pic16_aopOp(right,ic,FALSE) ;
13225         pic16_aopOp(result,ic,FALSE);
13226
13227         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13228
13229
13230         /* if the result is a bit */
13231         if (AOP_TYPE(result) == AOP_CRY) {
13232         
13233                 /* if the right size is a literal then
13234                  * we know what the value is */
13235                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13236
13237                 if (AOP_TYPE(right) == AOP_LIT) {
13238                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13239                                 pic16_popGet(AOP(result),0));
13240
13241                         if (((int) operandLitValue(right))) 
13242                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13243                                         AOP(result)->aopu.aop_dir,
13244                                         AOP(result)->aopu.aop_dir);
13245                         else
13246                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13247                                         AOP(result)->aopu.aop_dir,
13248                                         AOP(result)->aopu.aop_dir);
13249                         goto release;
13250                 }
13251
13252                 /* the right is also a bit variable */
13253                 if (AOP_TYPE(right) == AOP_CRY) {
13254                         emitCLRC;
13255                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13256
13257                         pic16_emitcode("clrc","");
13258                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13259                                 AOP(right)->aopu.aop_dir,
13260                                 AOP(right)->aopu.aop_dir);
13261                         pic16_aopPut(AOP(result),"c",0);
13262                         goto release ;
13263                 }
13264
13265                 /* we need to or */
13266                 if (AOP_TYPE(right) == AOP_REG) {
13267                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13268                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13269                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13270                 }
13271                 pic16_toBoolean(right);
13272                 pic16_aopPut(AOP(result),"a",0);
13273                 goto release ;
13274         }
13275
13276         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13277           int offset = 1;
13278
13279                 size = AOP_SIZE(result);
13280
13281                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13282
13283                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13284                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13285                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13286
13287                 while (size--)
13288                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13289
13290                 goto release;
13291         }
13292
13293         if(IS_BITFIELD(getSpec(restype))
13294           && IS_BITFIELD(getSpec(rtype))) {
13295           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13296         }
13297
13298         /* if they are the same size : or less */
13299         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13300
13301                 /* if they are in the same place */
13302                 if (pic16_sameRegs(AOP(right),AOP(result)))
13303                         goto release;
13304
13305                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13306 #if 0
13307                 if (IS_PTR_CONST(rtype))
13308 #else
13309                 if (IS_CODEPTR(rtype))
13310 #endif
13311                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13312
13313 #if 0
13314                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13315 #else
13316                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13317 #endif
13318                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13319
13320 #if 0
13321                 if(AOP_TYPE(right) == AOP_IMMD) {
13322                   pCodeOp *pcop0, *pcop1, *pcop2;
13323                   symbol *sym = OP_SYMBOL( right );
13324
13325                         size = AOP_SIZE(result);
13326                         /* low */
13327                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13328                         /* high */
13329                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13330                         /* upper */
13331                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13332         
13333                         if (size == 3) {
13334                                 pic16_emitpcode(POC_MOVLW, pcop0);
13335                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13336                                 pic16_emitpcode(POC_MOVLW, pcop1);
13337                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13338                                 pic16_emitpcode(POC_MOVLW, pcop2);
13339                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13340                         } else
13341                         if (size == 2) {
13342                                 pic16_emitpcode(POC_MOVLW, pcop0);
13343                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13344                                 pic16_emitpcode(POC_MOVLW, pcop1);
13345                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13346                         } else {
13347                                 pic16_emitpcode(POC_MOVLW, pcop0);
13348                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13349                         }
13350                 } else
13351 #endif
13352                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13353                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13354                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13355                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13356                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13357                         if(AOP_SIZE(result) <2)
13358                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13359                 } else {
13360                         /* if they in different places then copy */
13361                         size = AOP_SIZE(result);
13362                         offset = 0 ;
13363                         while (size--) {
13364                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13365                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13366                                 offset++;
13367                         }
13368                 }
13369                 goto release;
13370         }
13371
13372         /* if the result is of type pointer */
13373         if (IS_PTR(ctype)) {
13374           int p_type;
13375           sym_link *type = operandType(right);
13376           sym_link *etype = getSpec(type);
13377
13378                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13379
13380                 /* pointer to generic pointer */
13381                 if (IS_GENPTR(ctype)) {
13382                   char *l = zero;
13383             
13384                         if (IS_PTR(type)) 
13385                                 p_type = DCL_TYPE(type);
13386                         else {
13387                 /* we have to go by the storage class */
13388                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13389
13390 /*              if (SPEC_OCLS(etype)->codesp )  */
13391 /*                  p_type = CPOINTER ;  */
13392 /*              else */
13393 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13394 /*                      p_type = FPOINTER ; */
13395 /*                  else */
13396 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13397 /*                          p_type = PPOINTER; */
13398 /*                      else */
13399 /*                          if (SPEC_OCLS(etype) == idata ) */
13400 /*                              p_type = IPOINTER ; */
13401 /*                          else */
13402 /*                              p_type = POINTER ; */
13403             }
13404                 
13405             /* the first two bytes are known */
13406       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13407             size = GPTRSIZE - 1; 
13408             offset = 0 ;
13409             while (size--) {
13410               if(offset < AOP_SIZE(right)) {
13411                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13412                 mov2f(AOP(result), AOP(right), offset);
13413 /*
13414                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13415                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13416                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13417                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13418                 } else { 
13419                   
13420                   pic16_aopPut(AOP(result),
13421                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13422                          offset);
13423                 }
13424 */
13425               } else 
13426                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13427               offset++;
13428             }
13429             /* the last byte depending on type */
13430             switch (p_type) {
13431             case IPOINTER:
13432             case POINTER:
13433                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13434                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13435 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13436                 break;
13437
13438             case CPOINTER:
13439                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13440                 break;
13441
13442             case FPOINTER:
13443               pic16_emitcode(";BUG!? ","%d",__LINE__);
13444                 l = one;
13445                 break;
13446             case PPOINTER:
13447               pic16_emitcode(";BUG!? ","%d",__LINE__);
13448                 l = "#0x03";
13449                 break;
13450
13451             case GPOINTER:
13452                 if (GPTRSIZE > AOP_SIZE(right)) {
13453                   // assume data pointer... THIS MIGHT BE WRONG!
13454                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13455                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13456                 } else {
13457                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13458                 }
13459               break;
13460               
13461             default:
13462                 /* this should never happen */
13463                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13464                        "got unknown pointer type");
13465                 exit(1);
13466             }
13467             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13468             goto release ;
13469         }
13470         
13471         /* just copy the pointers */
13472         size = AOP_SIZE(result);
13473         offset = 0 ;
13474         while (size--) {
13475             pic16_aopPut(AOP(result),
13476                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13477                    offset);
13478             offset++;
13479         }
13480         goto release ;
13481     }
13482     
13483
13484
13485     /* so we now know that the size of destination is greater
13486     than the size of the source.
13487     Now, if the next iCode is an operator then we might be
13488     able to optimize the operation without performing a cast.
13489     */
13490     if(genMixedOperation(ic))
13491       goto release;
13492
13493     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13494     
13495     /* we move to result for the size of source */
13496     size = AOP_SIZE(right);
13497     offset = 0 ;
13498     while (size--) {
13499       mov2f(AOP(result), AOP(right), offset);
13500       offset++;
13501     }
13502
13503     /* now depending on the sign of the destination */
13504     size = AOP_SIZE(result) - AOP_SIZE(right);
13505     /* if unsigned or not an integral type */
13506     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13507       while (size--)
13508         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13509     } else {
13510       /* we need to extend the sign :( */
13511
13512       if(size == 1) {
13513         /* Save one instruction of casting char to int */
13514         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13515         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13516         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13517       } else {
13518         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13519
13520         if(offset)
13521           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13522         else
13523           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13524         
13525         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13526
13527         while (size--)
13528           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13529       }
13530     }
13531
13532 release:
13533     pic16_freeAsmop(right,NULL,ic,TRUE);
13534     pic16_freeAsmop(result,NULL,ic,TRUE);
13535
13536 }
13537
13538 /*-----------------------------------------------------------------*/
13539 /* genDjnz - generate decrement & jump if not zero instrucion      */
13540 /*-----------------------------------------------------------------*/
13541 static int genDjnz (iCode *ic, iCode *ifx)
13542 {
13543     symbol *lbl, *lbl1;
13544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13545
13546     if (!ifx)
13547         return 0;
13548     
13549     /* if the if condition has a false label
13550        then we cannot save */
13551     if (IC_FALSE(ifx))
13552         return 0;
13553
13554     /* if the minus is not of the form 
13555        a = a - 1 */
13556     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13557         !IS_OP_LITERAL(IC_RIGHT(ic)))
13558         return 0;
13559
13560     if (operandLitValue(IC_RIGHT(ic)) != 1)
13561         return 0;
13562
13563     /* if the size of this greater than one then no
13564        saving */
13565     if (getSize(operandType(IC_RESULT(ic))) > 1)
13566         return 0;
13567
13568     /* otherwise we can save BIG */
13569     lbl = newiTempLabel(NULL);
13570     lbl1= newiTempLabel(NULL);
13571
13572     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13573     
13574     if (IS_AOP_PREG(IC_RESULT(ic))) {
13575         pic16_emitcode("dec","%s",
13576                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13577         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13578         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13579     } else {    
13580
13581
13582       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13583       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13584
13585       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13586       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13587
13588     }
13589     
13590     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13591     ifx->generated = 1;
13592     return 1;
13593 }
13594
13595 /*-----------------------------------------------------------------*/
13596 /* genReceive - generate code for a receive iCode                  */
13597 /*-----------------------------------------------------------------*/
13598 static void genReceive (iCode *ic)
13599 {    
13600
13601   FENTRY;
13602
13603 #if 0
13604   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13605         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13606 #endif
13607 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13608
13609   if (isOperandInFarSpace(IC_RESULT(ic))
13610       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13611           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13612
13613     int size = getSize(operandType(IC_RESULT(ic)));
13614     int offset =  pic16_fReturnSizePic - size;
13615
13616       assert( 0 );
13617       while (size--) {
13618         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13619                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13620                       offset++;
13621         }
13622
13623       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13624
13625       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13626       size = AOP_SIZE(IC_RESULT(ic));
13627       offset = 0;
13628       while (size--) {
13629         pic16_emitcode ("pop","acc");
13630         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13631       }
13632   } else {
13633     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13634     _G.accInUse++;
13635     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13636     _G.accInUse--;
13637
13638     /* set pseudo stack pointer to where it should be - dw*/
13639     GpsuedoStkPtr = ic->parmBytes;
13640
13641     /* setting GpsuedoStkPtr has side effects here: */
13642     assignResultValue(IC_RESULT(ic), 0);
13643   }
13644
13645   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13646 }
13647
13648 /*-----------------------------------------------------------------*/
13649 /* genDummyRead - generate code for dummy read of volatiles        */
13650 /*-----------------------------------------------------------------*/
13651 static void
13652 genDummyRead (iCode * ic)
13653 {
13654   operand *op;
13655   int i;
13656
13657   op = IC_RIGHT(ic);
13658   if (op && IS_SYMOP(op)) {
13659     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13660       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13661       return;
13662     }
13663     pic16_aopOp (op, ic, FALSE);
13664     for (i=0; i < AOP_SIZE(op); i++) {
13665       // may need to protect this from the peepholer -- this is not nice but works...
13666       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13667       pic16_mov2w (AOP(op),i);
13668       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13669     } // for i
13670     pic16_freeAsmop (op, NULL, ic, TRUE);
13671   } else if (op) {
13672     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13673   } // if
13674 }
13675
13676 /*-----------------------------------------------------------------*/
13677 /* genpic16Code - generate code for pic16 based controllers        */
13678 /*-----------------------------------------------------------------*/
13679 /*
13680  * At this point, ralloc.c has gone through the iCode and attempted
13681  * to optimize in a way suitable for a PIC. Now we've got to generate
13682  * PIC instructions that correspond to the iCode.
13683  *
13684  * Once the instructions are generated, we'll pass through both the
13685  * peep hole optimizer and the pCode optimizer.
13686  *-----------------------------------------------------------------*/
13687
13688 void genpic16Code (iCode *lic)
13689 {
13690   iCode *ic;
13691   int cln = 0;
13692
13693     lineHead = lineCurr = NULL;
13694
13695     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13696     pic16_addpBlock(pb);
13697
13698 #if 0
13699     /* if debug information required */
13700     if (options.debug && currFunc) {
13701       if (currFunc) {
13702         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13703       }
13704     }
13705 #endif
13706
13707     for (ic = lic ; ic ; ic = ic->next ) {
13708
13709       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13710       if ( cln != ic->lineno ) {
13711         if ( options.debug ) {
13712           debugFile->writeCLine (ic);
13713         }
13714         
13715         if(!options.noCcodeInAsm) {
13716           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13717               printCLine(ic->filename, ic->lineno)));
13718         }
13719
13720         cln = ic->lineno ;
13721       }
13722         
13723       if(options.iCodeInAsm) {
13724         char *l;
13725
13726           /* insert here code to print iCode as comment */
13727           l = Safe_strdup(printILine(ic));
13728           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13729       }
13730         
13731       /* if the result is marked as
13732        * spilt and rematerializable or code for
13733        * this has already been generated then
13734        * do nothing */
13735       if (resultRemat(ic) || ic->generated ) 
13736         continue ;
13737         
13738       /* depending on the operation */
13739       switch (ic->op) {
13740         case '!' :
13741           pic16_genNot(ic);
13742           break;
13743             
13744         case '~' :
13745           pic16_genCpl(ic);
13746           break;
13747             
13748         case UNARYMINUS:
13749           genUminus (ic);
13750           break;
13751             
13752         case IPUSH:
13753           genIpush (ic);
13754           break;
13755             
13756         case IPOP:
13757           /* IPOP happens only when trying to restore a 
13758            * spilt live range, if there is an ifx statement
13759            * following this pop then the if statement might
13760            * be using some of the registers being popped which
13761            * would destroy the contents of the register so
13762            * we need to check for this condition and handle it */
13763            if (ic->next
13764              && ic->next->op == IFX
13765              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13766                genIfx (ic->next,ic);
13767           else
13768             genIpop (ic);
13769           break; 
13770             
13771         case CALL:
13772           genCall (ic);
13773           break;
13774             
13775         case PCALL:
13776           genPcall (ic);
13777           break;
13778             
13779         case FUNCTION:
13780           genFunction (ic);
13781           break;
13782             
13783         case ENDFUNCTION:
13784           genEndFunction (ic);
13785           break;
13786             
13787         case RETURN:
13788           genRet (ic);
13789           break;
13790             
13791         case LABEL:
13792           genLabel (ic);
13793           break;
13794             
13795         case GOTO:
13796           genGoto (ic);
13797           break;
13798             
13799         case '+' :
13800           pic16_genPlus (ic) ;
13801           break;
13802             
13803         case '-' :
13804           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13805             pic16_genMinus (ic);
13806           break;
13807
13808         case '*' :
13809           genMult (ic);
13810           break;
13811             
13812         case '/' :
13813           genDiv (ic) ;
13814           break;
13815             
13816         case '%' :
13817           genMod (ic);
13818           break;
13819             
13820         case '>' :
13821           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13822           break;
13823             
13824         case '<' :
13825           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13826           break;
13827             
13828         case LE_OP:
13829         case GE_OP:
13830         case NE_OP:
13831           /* note these two are xlated by algebraic equivalence
13832            * during parsing SDCC.y */
13833           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13834             "got '>=' or '<=' shouldn't have come here");
13835           break;
13836
13837         case EQ_OP:
13838           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13839           break;            
13840             
13841         case AND_OP:
13842           genAndOp (ic);
13843           break;
13844             
13845         case OR_OP:
13846           genOrOp (ic);
13847           break;
13848             
13849         case '^' :
13850           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13851           break;
13852             
13853         case '|' :
13854           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13855           break;
13856             
13857         case BITWISEAND:
13858           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13859           break;
13860             
13861         case INLINEASM:
13862           genInline (ic);
13863           break;
13864             
13865         case RRC:
13866           genRRC (ic);
13867           break;
13868             
13869         case RLC:
13870           genRLC (ic);
13871           break;
13872             
13873         case GETHBIT:
13874           genGetHbit (ic);
13875           break;
13876             
13877         case LEFT_OP:
13878           genLeftShift (ic);
13879           break;
13880             
13881         case RIGHT_OP:
13882           genRightShift (ic);
13883           break;
13884             
13885         case GET_VALUE_AT_ADDRESS:
13886           genPointerGet(ic);
13887           break;
13888             
13889         case '=' :
13890           if (POINTER_SET(ic))
13891             genPointerSet(ic);
13892           else
13893             genAssign(ic);
13894           break;
13895             
13896         case IFX:
13897           genIfx (ic,NULL);
13898           break;
13899             
13900         case ADDRESS_OF:
13901           genAddrOf (ic);
13902           break;
13903             
13904         case JUMPTABLE:
13905           genJumpTab (ic);
13906           break;
13907             
13908         case CAST:
13909           genCast (ic);
13910           break;
13911             
13912         case RECEIVE:
13913           genReceive(ic);
13914           break;
13915             
13916         case SEND:
13917           addSet(&_G.sendSet,ic);
13918           break;
13919
13920         case DUMMY_READ_VOLATILE:
13921           genDummyRead (ic);
13922           break;
13923
13924         default :
13925           ic = ic;
13926       }
13927     }
13928
13929
13930     /* now we are ready to call the
13931        peep hole optimizer */
13932     if (!options.nopeep)
13933       peepHole (&lineHead);
13934
13935     /* now do the actual printing */
13936     printLine (lineHead, codeOutFile);
13937
13938 #ifdef PCODE_DEBUG
13939     DFPRINTF((stderr,"printing pBlock\n\n"));
13940     pic16_printpBlock(stdout,pb);
13941 #endif
13942
13943     return;
13944 }
13945