* src/pic16/gen.c: fixed bug #1106975,
[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 0
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->size = AOP_SIZE( IC_LEFT(ic) );
873         else if(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         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1258                                           getSize(sym->type), 
1259                                           sym->usl.spillLoc->offset, op);
1260         aop->size = getSize(sym->type);
1261
1262         return;
1263     }
1264
1265     {
1266       sym_link *type = operandType(op);
1267 #if 0
1268       if(IS_PTR_CONST(type)) 
1269 #else
1270       if(IS_CODEPTR(type)) 
1271 #endif
1272         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1273     }
1274
1275     /* must be in a register */
1276     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1277     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1278     aop->size = sym->nRegs;
1279     for ( i = 0 ; i < sym->nRegs ;i++)
1280         aop->aopu.aop_reg[i] = sym->regs[i];
1281 }
1282
1283 /*-----------------------------------------------------------------*/
1284 /* pic16_freeAsmop - free up the asmop given to an operand               */
1285 /*----------------------------------------------------------------*/
1286 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1287 {   
1288     asmop *aop ;
1289
1290     if (!op)
1291         aop = aaop;
1292     else 
1293         aop = op->aop;
1294
1295     if (!aop)
1296         return ;
1297
1298     if (aop->freed)
1299         goto dealloc; 
1300
1301     aop->freed = 1;
1302
1303     /* depending on the asmop type only three cases need work AOP_RO
1304        , AOP_R1 && AOP_STK */
1305 #if 1
1306     switch (aop->type) {
1307         case AOP_FSR0 :
1308             if (_G.fsr0Pushed ) {
1309                 if (pop) {
1310                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1311                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1312 //                    pic16_emitcode ("pop","ar0");
1313                     _G.fsr0Pushed--;
1314                 }
1315             }
1316             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1317             break;
1318
1319         case AOP_FSR2 :
1320             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1321             break;
1322
1323         case AOP_R0 :
1324             if (_G.r0Pushed ) {
1325                 if (pop) {
1326                     pic16_emitcode ("pop","ar0");     
1327                     _G.r0Pushed--;
1328                 }
1329             }
1330             bitVectUnSetBit(ic->rUsed,R0_IDX);
1331             break;
1332
1333         case AOP_R1 :
1334             if (_G.r1Pushed ) {
1335                 if (pop) {
1336                     pic16_emitcode ("pop","ar1");
1337                     _G.r1Pushed--;
1338                 }
1339             }
1340             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1341             break;
1342
1343         case AOP_STA:
1344           {
1345             int i;
1346
1347               /* we must store the result on stack */
1348               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1349                 // operands on stack are accessible via "FSR2 + index" with index
1350                 // starting at 2 for arguments and growing from 0 downwards for
1351                 // local variables (index == 0 is not assigned so we add one here)
1352                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1353                 if (soffs <= 0) {
1354                   assert (soffs < 0);
1355                   soffs++;
1356                 } // if
1357                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1358                 for(i=0;i<aop->size;i++) {
1359                   /* initialise for stack access via frame pointer */
1360                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1361                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1362                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1363                 }
1364         
1365                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1366               }
1367
1368               if(!_G.resDirect) {
1369                 for(i=0;i<aop->size;i++)
1370                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1371               }
1372               _G.resDirect = 0;
1373           }
1374           break;
1375 #if 0
1376         case AOP_STK :
1377         {
1378             int sz = aop->size;    
1379             int stk = aop->aopu.aop_stk + aop->size;
1380             bitVectUnSetBit(ic->rUsed,R0_IDX);
1381             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1382
1383             getFreePtr(ic,&aop,FALSE);
1384             
1385             if (options.stack10bit)
1386             {
1387                 /* I'm not sure what to do here yet... */
1388                 /* #STUB */
1389                 fprintf(stderr, 
1390                         "*** Warning: probably generating bad code for "
1391                         "10 bit stack mode.\n");
1392             }
1393             
1394             if (stk) {
1395                 pic16_emitcode ("mov","a,_bp");
1396                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1397                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1398             } else {
1399                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1400             }
1401
1402             while (sz--) {
1403                 pic16_emitcode("pop","acc");
1404                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1405                 if (!sz) break;
1406                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1407             }
1408             op->aop = aop;
1409             pic16_freeAsmop(op,NULL,ic,TRUE);
1410             if (_G.r0Pushed) {
1411                 pic16_emitcode("pop","ar0");
1412                 _G.r0Pushed--;
1413             }
1414
1415             if (_G.r1Pushed) {
1416                 pic16_emitcode("pop","ar1");
1417                 _G.r1Pushed--;
1418             }       
1419         }
1420 #endif
1421
1422     }
1423 #endif
1424
1425 dealloc:
1426     /* all other cases just dealloc */
1427     if (op ) {
1428         op->aop = NULL;
1429         if (IS_SYMOP(op)) {
1430             OP_SYMBOL(op)->aop = NULL;    
1431             /* if the symbol has a spill */
1432             if (SPIL_LOC(op))
1433                 SPIL_LOC(op)->aop = NULL;
1434         }
1435     }
1436 }
1437
1438 /*-----------------------------------------------------------------*/
1439 /* pic16_aopGet - for fetching value of the aop                          */
1440 /*-----------------------------------------------------------------*/
1441 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1442 {
1443     char *s = buffer ;
1444     char *rs;
1445
1446     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1447
1448     /* offset is greater than size then zero */
1449     if (offset > (aop->size - 1) &&
1450         aop->type != AOP_LIT)
1451         return zero;
1452
1453     /* depending on type */
1454     switch (aop->type) {
1455
1456     case AOP_FSR0:
1457     case AOP_FSR2:
1458       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1459       rs = Safe_calloc(1, strlen(s)+1);
1460       strcpy(rs, s);
1461       return (rs);
1462       
1463 #if 0
1464       /* if we need to increment it */
1465       while (offset > aop->coff)
1466         {
1467           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1468           aop->coff++;
1469         }
1470
1471       while (offset < aop->coff)
1472         {
1473           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1474           aop->coff--;
1475         }
1476       aop->coff = offset;
1477       if (aop->paged)
1478         {
1479           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1480           return (dname ? "acc" : "a");
1481         }
1482       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1483       rs = Safe_calloc (1, strlen (s) + 1);
1484       strcpy (rs, s);
1485       return rs;
1486 #endif
1487
1488         
1489     case AOP_IMMD:
1490         if (bit16) 
1491             sprintf (s,"%s",aop->aopu.aop_immd);
1492         else
1493             if (offset) 
1494                 sprintf(s,"(%s >> %d)",
1495                         aop->aopu.aop_immd,
1496                         offset*8);
1497             else
1498                 sprintf(s,"%s",
1499                         aop->aopu.aop_immd);
1500         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1501         rs = Safe_calloc(1,strlen(s)+1);
1502         strcpy(rs,s);   
1503         return rs;
1504         
1505     case AOP_DIR:
1506       if (offset) {
1507         sprintf(s,"(%s + %d)",
1508                 aop->aopu.aop_dir,
1509                 offset);
1510         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1511       } else
1512             sprintf(s,"%s",aop->aopu.aop_dir);
1513         rs = Safe_calloc(1,strlen(s)+1);
1514         strcpy(rs,s);   
1515         return rs;
1516         
1517     case AOP_REG:
1518       //if (dname) 
1519       //    return aop->aopu.aop_reg[offset]->dname;
1520       //else
1521             return aop->aopu.aop_reg[offset]->name;
1522         
1523     case AOP_CRY:
1524       //pic16_emitcode(";","%d",__LINE__);
1525       return aop->aopu.aop_dir;
1526         
1527     case AOP_ACC:
1528         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1529 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1530 //        assert( 0 );
1531 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1532         rs = Safe_strdup("WREG");
1533         return (rs);
1534
1535     case AOP_LIT:
1536         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1537         rs = Safe_calloc(1,strlen(s)+1);
1538         strcpy(rs,s);   
1539         return rs;
1540         
1541     case AOP_STR:
1542         aop->coff = offset ;
1543         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1544             dname)
1545             return "acc";
1546         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1547         
1548         return aop->aopu.aop_str[offset];
1549         
1550     case AOP_PCODE:
1551       {
1552         pCodeOp *pcop = aop->aopu.pcop;
1553         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1554         if(pcop->name) {
1555           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1556           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1557           if (offset) {
1558             sprintf(s,"(%s + %d)", pcop->name, offset);
1559           } else {
1560             sprintf(s,"%s", pcop->name);
1561           }
1562         } else
1563           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1564
1565       }
1566       rs = Safe_calloc(1,strlen(s)+1);
1567       strcpy(rs,s);   
1568       return rs;
1569
1570 #if 0
1571     case AOP_PAGED:
1572       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1573       if (offset) {
1574         sprintf(s,"(%s + %d)",
1575                 aop->aopu.aop_dir,
1576                 offset);
1577       } else
1578             sprintf(s,"%s",aop->aopu.aop_dir);
1579       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1580       rs = Safe_calloc(1,strlen(s)+1);
1581       strcpy(rs,s);   
1582       return rs;
1583 #endif
1584
1585     case AOP_STA:
1586         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1587         return (rs);
1588         
1589     case AOP_STK:
1590 //        pCodeOp *pcop = aop->aop
1591         break;
1592
1593     }
1594
1595     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1596     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1597            "aopget got unsupported aop->type");
1598     exit(0);
1599 }
1600
1601
1602
1603 /* lock has the following meaning: When allocating temporary registers
1604  * for stack variables storage, the value of the temporary register is
1605  * saved on stack. Its value is restored at the end. This procedure is
1606  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1607  * a possibility that before a call to pic16_aopOp, a temporary register
1608  * is allocated for a while and it is freed after some time, this will
1609  * mess the stack and values will not be restored properly. So use lock=1
1610  * to allocate temporary registers used internally by the programmer, and
1611  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1612  * to inform the compiler developer about a possible bug. This is an internal
1613  * feature for developing the compiler -- VR */
1614  
1615 int _TempReg_lock = 0;
1616 /*-----------------------------------------------------------------*/
1617 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1618 /*-----------------------------------------------------------------*/
1619 pCodeOp *pic16_popGetTempReg(int lock)
1620 {
1621   pCodeOp *pcop;
1622   symbol *cfunc;
1623
1624 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1625     if(_TempReg_lock) {
1626 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1627     }
1628     
1629     _TempReg_lock += lock;
1630     
1631     cfunc = currFunc;
1632     currFunc = NULL;
1633
1634     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1635     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1636       PCOR(pcop)->r->wasUsed=1;
1637       PCOR(pcop)->r->isFree=0;
1638
1639       /* push value on stack */
1640       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1641     }
1642
1643     currFunc = cfunc;
1644
1645   return pcop;
1646 }
1647
1648 /*-----------------------------------------------------------------*/
1649 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1650 /*                            don't save if inside v               */
1651 /*-----------------------------------------------------------------*/
1652 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1653 {
1654   pCodeOp *pcop;
1655   symbol *cfunc;
1656
1657 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1658
1659     if(_TempReg_lock) {
1660 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1661     }
1662
1663     _TempReg_lock += lock;
1664
1665     cfunc = currFunc;
1666     currFunc = NULL;
1667
1668     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1669     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1670       PCOR(pcop)->r->wasUsed=1;
1671       PCOR(pcop)->r->isFree=0;
1672
1673       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1674       /* push value on stack */
1675         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1676       }
1677     }
1678
1679     currFunc = cfunc;
1680
1681   return pcop;
1682 }
1683
1684
1685 /*-----------------------------------------------------------------*/
1686 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1687 /*-----------------------------------------------------------------*/
1688 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1689 {
1690   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1691
1692   _TempReg_lock -= lock;
1693
1694   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1695     PCOR(pcop)->r->isFree = 1;
1696     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1697   }
1698 }
1699 /*-----------------------------------------------------------------*/
1700 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1701 /*-----------------------------------------------------------------*/
1702 pCodeOp *pic16_popGetLabel(unsigned int key)
1703 {
1704
1705   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1706
1707   if(key>max_key)
1708     max_key = key;
1709
1710   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1711 }
1712
1713 /*-----------------------------------------------------------------*/
1714 /* pic16_popCopyReg - copy a pcode operator                              */
1715 /*-----------------------------------------------------------------*/
1716 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1717 {
1718   pCodeOpReg *pcor;
1719
1720   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1721   pcor->pcop.type = pc->pcop.type;
1722   if(pc->pcop.name) {
1723     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1724       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1725   } else
1726     pcor->pcop.name = NULL;
1727
1728   pcor->r = pc->r;
1729   pcor->rIdx = pc->rIdx;
1730   pcor->r->wasUsed=1;
1731   pcor->instance = pc->instance;
1732
1733 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1734
1735   return PCOP(pcor);
1736 }
1737
1738 /*-----------------------------------------------------------------*/
1739 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1740 /*-----------------------------------------------------------------*/
1741 pCodeOp *pic16_popGetLit(int lit)
1742 {
1743   return pic16_newpCodeOpLit(lit);
1744 }
1745
1746 /*-----------------------------------------------------------------*/
1747 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1748 /*-----------------------------------------------------------------*/
1749 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1750 {
1751   return pic16_newpCodeOpLit2(lit, arg2);
1752 }
1753
1754
1755 /*-----------------------------------------------------------------*/
1756 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1757 /*-----------------------------------------------------------------*/
1758 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1759 {
1760   return pic16_newpCodeOpImmd(name, offset,index, 0);
1761 }
1762
1763
1764 /*-----------------------------------------------------------------*/
1765 /* pic16_popGet - asm operator to pcode operator conversion              */
1766 /*-----------------------------------------------------------------*/
1767 pCodeOp *pic16_popGetWithString(char *str)
1768 {
1769   pCodeOp *pcop;
1770
1771
1772   if(!str) {
1773     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1774     exit (1);
1775   }
1776
1777   pcop = pic16_newpCodeOp(str,PO_STR);
1778
1779   return pcop;
1780 }
1781
1782 /*-----------------------------------------------------------------*/
1783 /* pic16_popRegFromString -                                        */
1784 /*-----------------------------------------------------------------*/
1785 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1786 {
1787
1788   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1789   pcop->type = PO_DIR;
1790
1791   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1792   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1793
1794   if(!str)
1795     str = "BAD_STRING";
1796
1797   pcop->name = Safe_calloc(1,strlen(str)+1);
1798   strcpy(pcop->name,str);
1799
1800   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1801
1802   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1803
1804   /* make sure that register doesn't exist,
1805    * and operand isn't NULL
1806    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1807   if((PCOR(pcop)->r == NULL) 
1808     && (op)
1809     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1810 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1811 //              __FUNCTION__, __LINE__, str, size, offset);
1812
1813     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1814     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1815
1816   }
1817   PCOR(pcop)->instance = offset;
1818
1819   return pcop;
1820 }
1821
1822 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1823 {
1824   pCodeOp *pcop;
1825
1826 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1827
1828         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1829         PCOR(pcop)->rIdx = rIdx;
1830         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1831
1832         PCOR(pcop)->r->isFree = 0;
1833         PCOR(pcop)->r->wasUsed = 1;
1834
1835         pcop->type = PCOR(pcop)->r->pc_type;
1836
1837   return pcop;
1838 }
1839
1840 /*---------------------------------------------------------------------------------*/
1841 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1842 /*                 VR 030601                                                       */
1843 /*---------------------------------------------------------------------------------*/
1844 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1845 {
1846   pCodeOpReg2 *pcop2;
1847   pCodeOp *temp;
1848   
1849         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1850
1851         /* comment the following check, so errors to throw up */
1852 //      if(!pcop2)return NULL;
1853
1854         temp = pic16_popGet(aop_dst, offset);
1855         pcop2->pcop2 = temp;
1856         
1857   return PCOP(pcop2);
1858 }
1859
1860
1861
1862 /*--------------------------------------------------------------------------------.-*/
1863 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1864 /*                  VR 030601 , adapted by Hans Dorn                                */
1865 /*--------------------------------------------------------------------------------.-*/
1866 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1867 {
1868   pCodeOpReg2 *pcop2;
1869  
1870         pcop2 = (pCodeOpReg2 *)src;
1871         pcop2->pcop2 = dst;
1872         
1873         return PCOP(pcop2);
1874 }
1875
1876
1877
1878 /*---------------------------------------------------------------------------------*/
1879 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1880 /*                     movff instruction                                           */
1881 /*---------------------------------------------------------------------------------*/
1882 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1883 {
1884   pCodeOpReg2 *pcop2;
1885
1886         if(!noalloc) {
1887                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1888                 pcop2->pcop2 = pic16_popCopyReg(dst);
1889         } else {
1890                 /* the pCodeOp may be already allocated */
1891                 pcop2 = (pCodeOpReg2 *)(src);
1892                 pcop2->pcop2 = (pCodeOp *)(dst);
1893         }
1894
1895   return PCOP(pcop2);
1896 }
1897
1898
1899 /*-----------------------------------------------------------------*/
1900 /* pic16_popGet - asm operator to pcode operator conversion              */
1901 /*-----------------------------------------------------------------*/
1902 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1903 {
1904   //char *s = buffer ;
1905   char *rs;
1906   pCodeOp *pcop;
1907
1908     FENTRY2;
1909     /* offset is greater than
1910     size then zero */
1911
1912 //    if (offset > (aop->size - 1) &&
1913 //        aop->type != AOP_LIT)
1914 //      return NULL;  //zero;
1915
1916     /* depending on type */
1917     switch (aop->type) {
1918         
1919     case AOP_R0:
1920     case AOP_R1:
1921     case AOP_DPTR:
1922     case AOP_DPTR2:
1923         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1924         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1925         assert( 0 );
1926         return NULL;
1927
1928
1929     case AOP_FSR0:
1930     case AOP_FSR2:
1931       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1932       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1933       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1934       PCOR(pcop)->r->wasUsed = 1;
1935       PCOR(pcop)->r->isFree = 0;
1936       
1937       PCOR(pcop)->instance = offset;
1938       pcop->type = PCOR(pcop)->r->pc_type;
1939       return (pcop);
1940
1941     case AOP_IMMD:
1942       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1943       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1944
1945     case AOP_STA:
1946       /* pCodeOp is already allocated from aopForSym */
1947         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1948         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1949           
1950       return (pcop);
1951       
1952     case AOP_ACC:
1953       {
1954         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1955
1956         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1957
1958         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1959         
1960         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1961         PCOR(pcop)->rIdx = rIdx;
1962         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1963         PCOR(pcop)->r->wasUsed=1;
1964         PCOR(pcop)->r->isFree=0;
1965
1966         PCOR(pcop)->instance = offset;
1967         pcop->type = PCOR(pcop)->r->pc_type;
1968 //      rs = aop->aopu.aop_reg[offset]->name;
1969 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1970         return pcop;
1971
1972
1973 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1974 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1975
1976 //      assert( 0 );
1977       }
1978         
1979     case AOP_DIR:
1980       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1981       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1982         
1983 #if 0
1984     case AOP_PAGED:
1985       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1986       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1987 #endif
1988
1989     case AOP_REG:
1990       {
1991         int rIdx;
1992         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1993         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1994
1995         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1996         
1997         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1998 //      pcop->type = PO_GPR_REGISTER;
1999         PCOR(pcop)->rIdx = rIdx;
2000         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2001         PCOR(pcop)->r->wasUsed=1;
2002         PCOR(pcop)->r->isFree=0;
2003
2004         PCOR(pcop)->instance = offset;
2005         pcop->type = PCOR(pcop)->r->pc_type;
2006         
2007         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2008         rs = aop->aopu.aop_reg[offset]->name;
2009         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2010         return pcop;
2011       }
2012
2013     case AOP_CRY:
2014         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2015
2016       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2017       PCOR(pcop)->instance = offset;
2018       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2019       //if(PCOR(pcop)->r == NULL)
2020       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2021       return pcop;
2022         
2023     case AOP_LIT:
2024         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2025       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2026
2027     case AOP_STR:
2028       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2029       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2030
2031       /*
2032       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2033       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2034       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2035       pcop->type = PCOR(pcop)->r->pc_type;
2036       pcop->name = PCOR(pcop)->r->name;
2037
2038       return pcop;
2039       */
2040
2041     case AOP_PCODE:
2042       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2043                           __LINE__, 
2044                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2045       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2046       switch( aop->aopu.pcop->type ) {
2047         case PO_DIR: PCOR(pcop)->instance += offset; break;
2048         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2049         default:
2050           assert( 0 );  /* should never reach here */;
2051       }
2052       return pcop;
2053     }
2054
2055     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2056            "pic16_popGet got unsupported aop->type");
2057     exit(0);
2058 }
2059 /*-----------------------------------------------------------------*/
2060 /* pic16_aopPut - puts a string for a aop                                */
2061 /*-----------------------------------------------------------------*/
2062 void pic16_aopPut (asmop *aop, char *s, int offset)
2063 {
2064     char *d = buffer ;
2065     symbol *lbl ;
2066
2067     return;
2068
2069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2070
2071     if (aop->size && offset > ( aop->size - 1)) {
2072         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2073                "pic16_aopPut got offset > aop->size");
2074         exit(0);
2075     }
2076
2077     /* will assign value to value */
2078     /* depending on where it is ofcourse */
2079     switch (aop->type) {
2080     case AOP_DIR:
2081       if (offset) {
2082         sprintf(d,"(%s + %d)",
2083                 aop->aopu.aop_dir,offset);
2084         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2085
2086       } else
2087             sprintf(d,"%s",aop->aopu.aop_dir);
2088         
2089         if (strcmp(d,s)) {
2090           DEBUGpic16_emitcode(";","%d",__LINE__);
2091           if(strcmp(s,"W"))
2092             pic16_emitcode("movf","%s,w",s);
2093           pic16_emitcode("movwf","%s",d);
2094
2095           if(strcmp(s,"W")) {
2096             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2097             if(offset >= aop->size) {
2098               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2099               break;
2100             } else
2101               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2102           }
2103
2104           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2105
2106
2107         }
2108         break;
2109         
2110     case AOP_REG:
2111       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2112         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2113           /*
2114             if (*s == '@'           ||
2115                 strcmp(s,"r0") == 0 ||
2116                 strcmp(s,"r1") == 0 ||
2117                 strcmp(s,"r2") == 0 ||
2118                 strcmp(s,"r3") == 0 ||
2119                 strcmp(s,"r4") == 0 ||
2120                 strcmp(s,"r5") == 0 ||
2121                 strcmp(s,"r6") == 0 || 
2122                 strcmp(s,"r7") == 0 )
2123                 pic16_emitcode("mov","%s,%s  ; %d",
2124                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2125             else
2126           */
2127
2128           if(strcmp(s,"W")==0 )
2129             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2130
2131           pic16_emitcode("movwf","%s",
2132                    aop->aopu.aop_reg[offset]->name);
2133
2134           if(strcmp(s,zero)==0) {
2135             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2136
2137           } else if(strcmp(s,"W")==0) {
2138             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2139             pcop->type = PO_GPR_REGISTER;
2140
2141             PCOR(pcop)->rIdx = -1;
2142             PCOR(pcop)->r = NULL;
2143
2144             DEBUGpic16_emitcode(";","%d",__LINE__);
2145             pcop->name = Safe_strdup(s);
2146             pic16_emitpcode(POC_MOVFW,pcop);
2147             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2148           } else if(strcmp(s,one)==0) {
2149             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2150             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2151           } else {
2152             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2153           }
2154         }
2155         break;
2156         
2157     case AOP_DPTR:
2158     case AOP_DPTR2:
2159     
2160     if (aop->type == AOP_DPTR2)
2161     {
2162         genSetDPTR(1);
2163     }
2164     
2165         if (aop->code) {
2166             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2167                    "pic16_aopPut writting to code space");
2168             exit(0);
2169         }
2170         
2171         while (offset > aop->coff) {
2172             aop->coff++;
2173             pic16_emitcode ("inc","dptr");
2174         }
2175         
2176         while (offset < aop->coff) {
2177             aop->coff-- ;
2178             pic16_emitcode("lcall","__decdptr");
2179         }
2180         
2181         aop->coff = offset;
2182         
2183         /* if not in accumulater */
2184         MOVA(s);        
2185         
2186         pic16_emitcode ("movx","@dptr,a");
2187         
2188     if (aop->type == AOP_DPTR2)
2189     {
2190         genSetDPTR(0);
2191     }
2192         break;
2193         
2194     case AOP_R0:
2195     case AOP_R1:
2196         while (offset > aop->coff) {
2197             aop->coff++;
2198             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2199         }
2200         while (offset < aop->coff) {
2201             aop->coff-- ;
2202             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2203         }
2204         aop->coff = offset;
2205         
2206         if (aop->paged) {
2207             MOVA(s);           
2208             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2209             
2210         } else
2211             if (*s == '@') {
2212                 MOVA(s);
2213                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2214             } else
2215                 if (strcmp(s,"r0") == 0 ||
2216                     strcmp(s,"r1") == 0 ||
2217                     strcmp(s,"r2") == 0 ||
2218                     strcmp(s,"r3") == 0 ||
2219                     strcmp(s,"r4") == 0 ||
2220                     strcmp(s,"r5") == 0 ||
2221                     strcmp(s,"r6") == 0 || 
2222                     strcmp(s,"r7") == 0 ) {
2223                     char buffer[10];
2224                     sprintf(buffer,"a%s",s);
2225                     pic16_emitcode("mov","@%s,%s",
2226                              aop->aopu.aop_ptr->name,buffer);
2227                 } else
2228                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2229         
2230         break;
2231         
2232     case AOP_STK:
2233         if (strcmp(s,"a") == 0)
2234             pic16_emitcode("push","acc");
2235         else
2236             pic16_emitcode("push","%s",s);
2237         
2238         break;
2239         
2240     case AOP_CRY:
2241         /* if bit variable */
2242         if (!aop->aopu.aop_dir) {
2243             pic16_emitcode("clr","a");
2244             pic16_emitcode("rlc","a");
2245         } else {
2246             if (s == zero) 
2247                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2248             else
2249                 if (s == one)
2250                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2251                 else
2252                     if (!strcmp(s,"c"))
2253                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2254                     else {
2255                         lbl = newiTempLabel(NULL);
2256                         
2257                         if (strcmp(s,"a")) {
2258                             MOVA(s);
2259                         }
2260                         pic16_emitcode("clr","c");
2261                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2262                         pic16_emitcode("cpl","c");
2263                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2264                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2265                     }
2266         }
2267         break;
2268         
2269     case AOP_STR:
2270         aop->coff = offset;
2271         if (strcmp(aop->aopu.aop_str[offset],s))
2272             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2273         break;
2274         
2275     case AOP_ACC:
2276         aop->coff = offset;
2277         if (!offset && (strcmp(s,"acc") == 0))
2278             break;
2279         
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     default :
2285         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2286 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2287 //             "pic16_aopPut got unsupported aop->type");
2288 //      exit(0);    
2289     }    
2290
2291 }
2292
2293 /*-----------------------------------------------------------------*/
2294 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2295 /*-----------------------------------------------------------------*/
2296 void pic16_mov2w (asmop *aop, int offset)
2297 {
2298   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2299
2300   if(is_LitAOp(aop))
2301     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2302   else
2303     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2304 }
2305
2306 static void mov2f(asmop *dst, asmop *src, int offset)
2307 {
2308   if(is_LitAOp(src)) {
2309     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2310     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2311   } else {
2312     if(pic16_sameRegsOfs(src, dst, offset))return;
2313     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2314                       pic16_popGet(dst, offset)));
2315   }
2316 }
2317
2318 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2319 {
2320   if(is_LitAOp(src)) {
2321     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2322     pic16_emitpcode(POC_MOVWF, dst);
2323   } else {
2324     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2325   }
2326 }
2327
2328 void pic16_testStackOverflow(void)
2329 {
2330 #define GSTACK_TEST_NAME        "__gstack_test"
2331
2332   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2333   
2334   {
2335     symbol *sym;
2336
2337       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2338       strcpy(sym->rname, GSTACK_TEST_NAME);
2339       checkAddSym(&externs, sym);
2340   }
2341
2342 }
2343
2344 /* push pcop into stack */
2345 void pic16_pushpCodeOp(pCodeOp *pcop)
2346 {
2347 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2348   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2349   if(pic16_options.gstack)
2350     pic16_testStackOverflow();
2351     
2352 }
2353
2354 /* pop pcop from stack */
2355 void pic16_poppCodeOp(pCodeOp *pcop)
2356 {
2357   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2358   if(pic16_options.gstack)
2359     pic16_testStackOverflow();
2360 }
2361
2362
2363 /*-----------------------------------------------------------------*/
2364 /* pushw - pushes wreg to stack                                    */
2365 /*-----------------------------------------------------------------*/
2366 void pushw(void)
2367 {
2368   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2369   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2370   if(pic16_options.gstack)
2371     pic16_testStackOverflow();
2372 }
2373
2374                 
2375 /*-----------------------------------------------------------------*/
2376 /* pushaop - pushes aop to stack                                   */
2377 /*-----------------------------------------------------------------*/
2378 void pushaop(asmop *aop, int offset)
2379 {
2380   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2381
2382   if(is_LitAOp(aop)) {
2383     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2384     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2385   } else {
2386     pic16_emitpcode(POC_MOVFF,
2387       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2388   }
2389
2390   if(pic16_options.gstack)
2391     pic16_testStackOverflow();
2392 }
2393
2394 /*-----------------------------------------------------------------*/
2395 /* popaop - pops aop from stack                                    */
2396 /*-----------------------------------------------------------------*/
2397 void popaop(asmop *aop, int offset)
2398 {
2399   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2400   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2401   if(pic16_options.gstack)
2402     pic16_testStackOverflow();
2403 }
2404
2405 void popaopidx(asmop *aop, int offset, int index)
2406 {
2407   int ofs=1;
2408
2409     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2410
2411     if(STACK_MODEL_LARGE)ofs++;
2412
2413     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2414     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2415     if(pic16_options.gstack)
2416       pic16_testStackOverflow();
2417 }
2418
2419 #if !(USE_GENERIC_SIGNED_SHIFT)
2420 /*-----------------------------------------------------------------*/
2421 /* reAdjustPreg - points a register back to where it should        */
2422 /*-----------------------------------------------------------------*/
2423 static void reAdjustPreg (asmop *aop)
2424 {
2425     int size ;
2426
2427     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2428     aop->coff = 0;
2429     if ((size = aop->size) <= 1)
2430         return ;
2431     size-- ;
2432     switch (aop->type) {
2433         case AOP_R0 :
2434         case AOP_R1 :
2435             while (size--)
2436                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2437             break;          
2438         case AOP_DPTR :
2439         case AOP_DPTR2:
2440             if (aop->type == AOP_DPTR2)
2441             {
2442                 genSetDPTR(1);
2443             } 
2444             while (size--)
2445             {
2446                 pic16_emitcode("lcall","__decdptr");
2447             }
2448                 
2449             if (aop->type == AOP_DPTR2)
2450             {
2451                 genSetDPTR(0);
2452             }                
2453             break;  
2454
2455     }   
2456
2457 }
2458 #endif
2459
2460 #if 0
2461 /*-----------------------------------------------------------------*/
2462 /* opIsGptr: returns non-zero if the passed operand is             */   
2463 /* a generic pointer type.                                         */
2464 /*-----------------------------------------------------------------*/ 
2465 static int opIsGptr(operand *op)
2466 {
2467     sym_link *type = operandType(op);
2468     
2469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2470     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2471     {
2472         return 1;
2473     }
2474     return 0;        
2475 }
2476 #endif
2477
2478 /*-----------------------------------------------------------------*/
2479 /* pic16_getDataSize - get the operand data size                         */
2480 /*-----------------------------------------------------------------*/
2481 int pic16_getDataSize(operand *op)
2482 {
2483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2484
2485
2486     return AOP_SIZE(op);
2487
2488     // tsd- in the pic port, the genptr size is 1, so this code here
2489     // fails. ( in the 8051 port, the size was 4).
2490 #if 0
2491     int size;
2492     size = AOP_SIZE(op);
2493     if (size == GPTRSIZE)
2494     {
2495         sym_link *type = operandType(op);
2496         if (IS_GENPTR(type))
2497         {
2498             /* generic pointer; arithmetic operations
2499              * should ignore the high byte (pointer type).
2500              */
2501             size--;
2502     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2503         }
2504     }
2505     return size;
2506 #endif
2507 }
2508
2509 /*-----------------------------------------------------------------*/
2510 /* pic16_outAcc - output Acc                                             */
2511 /*-----------------------------------------------------------------*/
2512 void pic16_outAcc(operand *result)
2513 {
2514   int size,offset;
2515   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2516   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2517
2518
2519   size = pic16_getDataSize(result);
2520   if(size){
2521     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2522     size--;
2523     offset = 1;
2524     /* unsigned or positive */
2525     while(size--)
2526       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2527   }
2528
2529 }
2530
2531 /*-----------------------------------------------------------------*/
2532 /* pic16_outBitC - output a bit C                                  */
2533 /*                 Move to result the value of Carry flag -- VR    */
2534 /*-----------------------------------------------------------------*/
2535 void pic16_outBitC(operand *result)
2536 {
2537   int i;
2538
2539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2540
2541     /* if the result is bit */
2542     if (AOP_TYPE(result) == AOP_CRY) {
2543         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2544         pic16_aopPut(AOP(result),"c",0);
2545     } else {
2546
2547         i = AOP_SIZE(result);
2548         while(i--) {
2549                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2550         }
2551         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2552     }
2553 }
2554
2555 /*-----------------------------------------------------------------*/
2556 /* pic16_outBitOp - output a bit from Op                           */
2557 /*                 Move to result the value of set/clr op -- VR    */
2558 /*-----------------------------------------------------------------*/
2559 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2560 {
2561   int i;
2562
2563     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2564
2565     /* if the result is bit */
2566     if (AOP_TYPE(result) == AOP_CRY) {
2567         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2568         pic16_aopPut(AOP(result),"c",0);
2569     } else {
2570
2571         i = AOP_SIZE(result);
2572         while(i--) {
2573                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2574         }
2575         pic16_emitpcode(POC_RRCF, pcop);          
2576         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2577     }
2578 }
2579
2580 /*-----------------------------------------------------------------*/
2581 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2582 /*-----------------------------------------------------------------*/
2583 void pic16_toBoolean(operand *oper)
2584 {
2585     int size = AOP_SIZE(oper) - 1;
2586     int offset = 1;
2587
2588     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2589
2590     if ( AOP_TYPE(oper) != AOP_ACC) {
2591       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2592     }
2593     while (size--) {
2594       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2595     }
2596 }
2597
2598
2599 #if !defined(GEN_Not)
2600 /*-----------------------------------------------------------------*/
2601 /* genNot - generate code for ! operation                          */
2602 /*-----------------------------------------------------------------*/
2603 static void pic16_genNot (iCode *ic)
2604 {
2605   symbol *tlbl;
2606   int size;
2607
2608   FENTRY;
2609   /* assign asmOps to operand & result */
2610   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2611   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2612
2613   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2614   /* if in bit space then a special case */
2615   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2616     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2617       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2618       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2619     } else {
2620       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2621       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2622       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2623     }
2624     goto release;
2625   }
2626
2627   size = AOP_SIZE(IC_LEFT(ic));
2628   if(size == 1) {
2629     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2630     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2631     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2632     goto release;
2633   }
2634   pic16_toBoolean(IC_LEFT(ic));
2635
2636   tlbl = newiTempLabel(NULL);
2637   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2638   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2639   pic16_outBitC(IC_RESULT(ic));
2640
2641  release:    
2642   /* release the aops */
2643   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2644   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2645 }
2646 #endif
2647
2648
2649 #if !defined(GEN_Cpl)
2650 /*-----------------------------------------------------------------*/
2651 /* genCpl - generate code for complement                           */
2652 /*-----------------------------------------------------------------*/
2653 static void pic16_genCpl (iCode *ic)
2654 {
2655   int offset = 0;
2656   int size ;
2657
2658     FENTRY;
2659     /* assign asmOps to operand & result */
2660     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2661     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2662
2663     /* if both are in bit space then 
2664     a special case */
2665     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2666         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2667
2668         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2669         pic16_emitcode("cpl","c"); 
2670         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2671         goto release; 
2672     } 
2673
2674     size = AOP_SIZE(IC_RESULT(ic));
2675     while (size--) {
2676 /*
2677         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2678         MOVA(l);       
2679         pic16_emitcode("cpl","a");
2680         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2681 */
2682         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2683               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2684         } else {
2685                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2686                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2687         }
2688         offset++;
2689
2690     }
2691
2692
2693 release:
2694     /* release the aops */
2695     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2696     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2697 }
2698 #endif
2699
2700 /*-----------------------------------------------------------------*/
2701 /* genUminusFloat - unary minus for floating points                */
2702 /*-----------------------------------------------------------------*/
2703 static void genUminusFloat(operand *op,operand *result)
2704 {
2705   int size ,offset =0 ;
2706   
2707     FENTRY;
2708     /* for this we just need to flip the 
2709     first it then copy the rest in place */
2710     size = AOP_SIZE(op);
2711
2712     while(size--) {
2713       mov2f(AOP(result), AOP(op), offset);
2714       offset++;
2715     }
2716     
2717     /* toggle the MSB's highest bit */
2718     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2719 }
2720
2721 /*-----------------------------------------------------------------*/
2722 /* genUminus - unary minus code generation                         */
2723 /*-----------------------------------------------------------------*/
2724 static void genUminus (iCode *ic)
2725 {
2726   int size, i;
2727   sym_link *optype, *rtype;
2728   symbol *label;
2729   int needLabel=0;
2730
2731     FENTRY;     
2732     
2733     /* assign asmops */
2734     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2735     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2736
2737     /* if both in bit space then special case */
2738     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2739       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2740         
2741         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2742         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2743         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2744         goto release; 
2745     } 
2746
2747     optype = operandType(IC_LEFT(ic));
2748     rtype = operandType(IC_RESULT(ic));
2749
2750     /* if float then do float stuff */
2751     if (IS_FLOAT(optype)) {
2752       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2753       goto release;
2754     }
2755
2756     /* otherwise subtract from zero by taking the 2's complement */
2757     size = AOP_SIZE(IC_LEFT(ic));
2758     label = newiTempLabel ( NULL );
2759     
2760     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2761       for (i=size-1; i > 0; i--) {
2762         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2763       } // for
2764       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2765       for (i=1; i < size; i++) {
2766         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2767         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2768       } // for
2769     } else {
2770       for (i=size-1; i >= 0; i--) {
2771         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2772         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2773       } // for
2774       if (size > 1) {
2775         for (i=0; i < size-2; i++) {
2776           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2777           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2778         } // for
2779         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2780       } // if
2781       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2782     }
2783     if (needLabel)
2784       pic16_emitpLabel (label->key);
2785
2786 release:
2787     /* release the aops */
2788     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2789     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2790 }
2791
2792 #if 0
2793 /*-----------------------------------------------------------------*/
2794 /* saveRegisters - will look for a call and save the registers     */
2795 /*-----------------------------------------------------------------*/
2796 static void saveRegisters(iCode *lic) 
2797 {
2798     int i;
2799     iCode *ic;
2800     bitVect *rsave;
2801     sym_link *dtype;
2802
2803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2804     /* look for call */
2805     for (ic = lic ; ic ; ic = ic->next) 
2806         if (ic->op == CALL || ic->op == PCALL)
2807             break;
2808
2809     if (!ic) {
2810         fprintf(stderr,"found parameter push with no function call\n");
2811         return ;
2812     }
2813
2814     /* if the registers have been saved already then
2815     do nothing */
2816     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2817         return ;
2818
2819     /* find the registers in use at this time 
2820     and push them away to safety */
2821     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2822                           ic->rUsed);
2823
2824     ic->regsSaved = 1;
2825     if (options.useXstack) {
2826         if (bitVectBitValue(rsave,R0_IDX))
2827             pic16_emitcode("mov","b,r0");
2828         pic16_emitcode("mov","r0,%s",spname);
2829         for (i = 0 ; i < pic16_nRegs ; i++) {
2830             if (bitVectBitValue(rsave,i)) {
2831                 if (i == R0_IDX)
2832                     pic16_emitcode("mov","a,b");
2833                 else
2834                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2835                 pic16_emitcode("movx","@r0,a");
2836                 pic16_emitcode("inc","r0");
2837             }
2838         }
2839         pic16_emitcode("mov","%s,r0",spname);
2840         if (bitVectBitValue(rsave,R0_IDX))
2841             pic16_emitcode("mov","r0,b");           
2842     }// else
2843     //for (i = 0 ; i < pic16_nRegs ; i++) {
2844     //    if (bitVectBitValue(rsave,i))
2845     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2846     //}
2847
2848     dtype = operandType(IC_LEFT(ic));
2849     if (currFunc && dtype && 
2850         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2851         IFFUNC_ISISR(currFunc->type) &&
2852         !ic->bankSaved) 
2853
2854         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2855
2856 }
2857 /*-----------------------------------------------------------------*/
2858 /* unsaveRegisters - pop the pushed registers                      */
2859 /*-----------------------------------------------------------------*/
2860 static void unsaveRegisters (iCode *ic)
2861 {
2862     int i;
2863     bitVect *rsave;
2864
2865     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2866     /* find the registers in use at this time 
2867     and push them away to safety */
2868     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2869                           ic->rUsed);
2870     
2871     if (options.useXstack) {
2872         pic16_emitcode("mov","r0,%s",spname);   
2873         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2874             if (bitVectBitValue(rsave,i)) {
2875                 pic16_emitcode("dec","r0");
2876                 pic16_emitcode("movx","a,@r0");
2877                 if (i == R0_IDX)
2878                     pic16_emitcode("mov","b,a");
2879                 else
2880                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2881             }       
2882
2883         }
2884         pic16_emitcode("mov","%s,r0",spname);
2885         if (bitVectBitValue(rsave,R0_IDX))
2886             pic16_emitcode("mov","r0,b");
2887     } //else
2888     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2889     //    if (bitVectBitValue(rsave,i))
2890     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2891     //}
2892
2893 }  
2894 #endif
2895
2896 #if 0  // patch 14
2897 /*-----------------------------------------------------------------*/
2898 /* pushSide -                                                      */
2899 /*-----------------------------------------------------------------*/
2900 static void pushSide(operand * oper, int size)
2901 {
2902         int offset = 0;
2903     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2904         while (size--) {
2905                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2906                 if (AOP_TYPE(oper) != AOP_REG &&
2907                     AOP_TYPE(oper) != AOP_DIR &&
2908                     strcmp(l,"a") ) {
2909                         pic16_emitcode("mov","a,%s",l);
2910                         pic16_emitcode("push","acc");
2911                 } else
2912                         pic16_emitcode("push","%s",l);
2913         }
2914 }
2915 #endif // patch 14
2916
2917 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2918 {
2919   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2920     pic16_emitpcode(POC_MOVFW, src);
2921     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2922   } else {
2923     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2924         src, pic16_popGet(AOP(op), offset)));
2925   }
2926 }
2927
2928
2929 /*-----------------------------------------------------------------*/
2930 /* assignResultValue - assign results to oper, rescall==1 is       */
2931 /*                     called from genCall() or genPcall()         */
2932 /*-----------------------------------------------------------------*/
2933 static void assignResultValue(operand * oper, int rescall)
2934 {
2935   int size = AOP_SIZE(oper);
2936   int offset=0;
2937   
2938     FENTRY2;
2939 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2940     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2941
2942     if(rescall) {
2943       /* assign result from a call/pcall function() */
2944                 
2945       /* function results are stored in a special order,
2946        * see top of file with Function return policy, or manual */
2947
2948       if(size <= 4) {
2949         /* 8-bits, result in WREG */
2950         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2951                         
2952         if(size>1) {
2953           /* 16-bits, result in PRODL:WREG */
2954           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2955         }
2956                         
2957         if(size>2) {
2958           /* 24-bits, result in PRODH:PRODL:WREG */
2959           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2960         }
2961                         
2962         if(size>3) {
2963           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2964           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2965         }
2966       
2967       } else {
2968         /* >32-bits, result on stack, and FSR0 points to beginning.
2969          * Fix stack when done */
2970         /* FIXME FIXME */
2971 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2972         while (size--) {
2973 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2974 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2975                 
2976           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2977           GpsuedoStkPtr++;
2978         }
2979                         
2980         /* fix stack */
2981         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2982         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2983         if(STACK_MODEL_LARGE) {
2984           emitSKPNC;
2985           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2986         }
2987       }                 
2988     } else {
2989       int areg = 0;             /* matching argument register */
2990       
2991 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2992       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2993
2994
2995       /* its called from genReceive (probably) -- VR */
2996       /* I hope this code will not be called from somewhere else in the future! 
2997        * We manually set the pseudo stack pointer in genReceive. - dw
2998        */
2999       if(!GpsuedoStkPtr && _G.useWreg) {
3000 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3001
3002         /* The last byte in the assignment is in W */
3003         if(areg <= GpsuedoStkPtr) {
3004           size--;
3005           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3006           offset++;
3007 //          debugf("receive from WREG\n", 0);
3008         }
3009         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3010       }
3011 //      GpsuedoStkPtr++;
3012       _G.stack_lat = AOP_SIZE(oper)-1;
3013
3014       while (size) {
3015         size--;
3016         GpsuedoStkPtr++;
3017         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3018 //        debugf("receive from STACK\n", 0);
3019         offset++;
3020       }
3021     }
3022 }
3023
3024
3025 /*-----------------------------------------------------------------*/
3026 /* genIpush - generate code for pushing this gets a little complex */
3027 /*-----------------------------------------------------------------*/
3028 static void genIpush (iCode *ic)
3029 {
3030 //  int size, offset=0;
3031
3032   FENTRY;
3033   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3034
3035   if(ic->parmPush) {
3036     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3037
3038     /* send to stack as normal */
3039     addSet(&_G.sendSet,ic);
3040 //    addSetHead(&_G.sendSet,ic);
3041     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3042   }
3043
3044         
3045 #if 0
3046     int size, offset = 0 ;
3047     char *l;
3048
3049
3050     /* if this is not a parm push : ie. it is spill push 
3051     and spill push is always done on the local stack */
3052     if (!ic->parmPush) {
3053
3054         /* and the item is spilt then do nothing */
3055         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3056             return ;
3057
3058         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3059         size = AOP_SIZE(IC_LEFT(ic));
3060         /* push it on the stack */
3061         while(size--) {
3062             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3063             if (*l == '#') {
3064                 MOVA(l);
3065                 l = "acc";
3066             }
3067             pic16_emitcode("push","%s",l);
3068         }
3069         return ;        
3070     }
3071
3072     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3073 #endif
3074 }
3075
3076 /*-----------------------------------------------------------------*/
3077 /* genIpop - recover the registers: can happen only for spilling   */
3078 /*-----------------------------------------------------------------*/
3079 static void genIpop (iCode *ic)
3080 {
3081   FENTRY;
3082   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3083 #if 0
3084     int size,offset ;
3085
3086
3087     /* if the temp was not pushed then */
3088     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3089         return ;
3090
3091     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3092     size = AOP_SIZE(IC_LEFT(ic));
3093     offset = (size-1);
3094     while (size--) 
3095         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3096                                    FALSE,TRUE));
3097
3098     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3099 #endif
3100 }
3101
3102 #if 0
3103 /*-----------------------------------------------------------------*/
3104 /* unsaverbank - restores the resgister bank from stack            */
3105 /*-----------------------------------------------------------------*/
3106 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3107 {
3108   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3109 #if 0
3110     int i;
3111     asmop *aop ;
3112     regs *r = NULL;
3113
3114     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3115     if (popPsw) {
3116         if (options.useXstack) {
3117             aop = newAsmop(0);
3118             r = getFreePtr(ic,&aop,FALSE);
3119             
3120             
3121             pic16_emitcode("mov","%s,_spx",r->name);
3122             pic16_emitcode("movx","a,@%s",r->name);
3123             pic16_emitcode("mov","psw,a");
3124             pic16_emitcode("dec","%s",r->name);
3125             
3126         }else
3127             pic16_emitcode ("pop","psw");
3128     }
3129
3130     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3131         if (options.useXstack) {       
3132             pic16_emitcode("movx","a,@%s",r->name);
3133             //pic16_emitcode("mov","(%s+%d),a",
3134             //       regspic16[i].base,8*bank+regspic16[i].offset);
3135             pic16_emitcode("dec","%s",r->name);
3136
3137         } else 
3138           pic16_emitcode("pop",""); //"(%s+%d)",
3139         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3140     }
3141
3142     if (options.useXstack) {
3143
3144         pic16_emitcode("mov","_spx,%s",r->name);
3145         pic16_freeAsmop(NULL,aop,ic,TRUE);
3146
3147     }
3148 #endif 
3149 }
3150
3151 /*-----------------------------------------------------------------*/
3152 /* saverbank - saves an entire register bank on the stack          */
3153 /*-----------------------------------------------------------------*/
3154 static void saverbank (int bank, iCode *ic, bool pushPsw)
3155 {
3156   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3157 #if 0
3158     int i;
3159     asmop *aop ;
3160     regs *r = NULL;
3161
3162     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3163     if (options.useXstack) {
3164
3165         aop = newAsmop(0);
3166         r = getFreePtr(ic,&aop,FALSE);  
3167         pic16_emitcode("mov","%s,_spx",r->name);
3168
3169     }
3170
3171     for (i = 0 ; i < pic16_nRegs ;i++) {
3172         if (options.useXstack) {
3173             pic16_emitcode("inc","%s",r->name);
3174             //pic16_emitcode("mov","a,(%s+%d)",
3175             //         regspic16[i].base,8*bank+regspic16[i].offset);
3176             pic16_emitcode("movx","@%s,a",r->name);           
3177         } else 
3178           pic16_emitcode("push","");// "(%s+%d)",
3179                      //regspic16[i].base,8*bank+regspic16[i].offset);
3180     }
3181     
3182     if (pushPsw) {
3183         if (options.useXstack) {
3184             pic16_emitcode("mov","a,psw");
3185             pic16_emitcode("movx","@%s,a",r->name);     
3186             pic16_emitcode("inc","%s",r->name);
3187             pic16_emitcode("mov","_spx,%s",r->name);       
3188             pic16_freeAsmop (NULL,aop,ic,TRUE);
3189             
3190         } else
3191             pic16_emitcode("push","psw");
3192         
3193         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3194     }
3195     ic->bankSaved = 1;
3196 #endif
3197 }
3198 #endif  /* 0 */
3199
3200
3201 static int wparamCmp(void *p1, void *p2)
3202 {
3203   return (!strcmp((char *)p1, (char *)p2));
3204 }
3205
3206 int inWparamList(char *s)
3207 {
3208   return isinSetWith(wparamList, s, wparamCmp);
3209
3210
3211
3212 /*-----------------------------------------------------------------*/
3213 /* genCall - generates a call statement                            */
3214 /*-----------------------------------------------------------------*/
3215 static void genCall (iCode *ic)
3216 {
3217   sym_link *ftype;   
3218   int stackParms=0;
3219   int use_wreg=0;
3220   int inwparam=0;
3221   char *fname;
3222   
3223     FENTRY;
3224
3225     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3226     /* if caller saves & we have not saved then */
3227 //    if (!ic->regsSaved)
3228 //      saveRegisters(ic);
3229
3230         /* initialise stackParms for IPUSH pushes */
3231 //      stackParms = psuedoStkPtr;
3232 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3233     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3234     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3235
3236 #if 0
3237     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3238 #endif
3239
3240     /* if send set is not empty the assign */
3241     if (_G.sendSet) {
3242       iCode *sic;
3243       int psuedoStkPtr=-1; 
3244       int firstTimeThruLoop = 1;
3245
3246
3247         /* reverse sendSet if function is not reentrant */
3248         if(!IFFUNC_ISREENT(ftype))
3249           _G.sendSet = reverseSet(_G.sendSet);
3250
3251         /* First figure how many parameters are getting passed */
3252         stackParms = 0;
3253         use_wreg = 0;
3254         
3255         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3256           int size;
3257 //          int offset = 0;
3258
3259             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3260             size = AOP_SIZE(IC_LEFT(sic));
3261
3262             stackParms += size;
3263
3264             /* pass the last byte through WREG */
3265             if(inwparam) {
3266
3267               while (size--) {
3268                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3269                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3270                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3271
3272                 if(!firstTimeThruLoop) {
3273                   /* If this is not the first time we've been through the loop
3274                    * then we need to save the parameter in a temporary
3275                    * register. The last byte of the last parameter is
3276                    * passed in W. */
3277
3278                   pushw();
3279 //                  --psuedoStkPtr;             // sanity check
3280                   use_wreg = 1;
3281                 }
3282                 
3283                 firstTimeThruLoop=0;
3284
3285                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3286
3287 //                offset++;
3288               }
3289             } else {
3290               /* all arguments are passed via stack */
3291               use_wreg = 0;
3292
3293               while (size--) {
3294                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3295                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3296                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3297
3298 //                pushaop(AOP(IC_LEFT(sic)), size);
3299                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3300                 pushw();
3301               }
3302             }
3303
3304             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3305           }
3306
3307           if(inwparam) {
3308             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3309               pushw();  /* save last parameter to stack if functions has varargs */
3310               use_wreg = 0;
3311             } else
3312               use_wreg = 1;
3313           } else use_wreg = 0;
3314
3315           _G.stackRegSet = _G.sendSet;
3316           _G.sendSet = NULL;
3317     }
3318
3319     /* make the call */
3320     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3321
3322     GpsuedoStkPtr=0;
3323     
3324     /* if we need to assign a result value */
3325     if ((IS_ITEMP(IC_RESULT(ic))
3326           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3327               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3328         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3329
3330       _G.accInUse++;
3331       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3332       _G.accInUse--;
3333
3334       assignResultValue(IC_RESULT(ic), 1);
3335
3336       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3337                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3338                 
3339       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3340     }
3341
3342     if(!stackParms && ic->parmBytes) {
3343       stackParms = ic->parmBytes;
3344     }
3345       
3346     stackParms -= use_wreg;
3347     
3348     if(stackParms>0) {
3349       if(stackParms == 1) {
3350         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3351       } else {
3352         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3353         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3354       }
3355       if(STACK_MODEL_LARGE) {
3356         emitSKPNC;
3357         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3358       }
3359     }
3360
3361 #if 0
3362     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3363 #endif
3364
3365     /* adjust the stack for parameters if required */
3366 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3367
3368 #if 0
3369       /* if register bank was saved then pop them */
3370       if (ic->bankSaved)
3371         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3372
3373       /* if we hade saved some registers then unsave them */
3374       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3375         unsaveRegisters (ic);
3376 #endif
3377 }
3378
3379
3380
3381 /*-----------------------------------------------------------------*/
3382 /* genPcall - generates a call by pointer statement                */
3383 /*            new version, created from genCall - HJD              */
3384 /*-----------------------------------------------------------------*/
3385 static void genPcall (iCode *ic)
3386 {
3387   sym_link *ftype, *fntype;
3388   int stackParms=0;
3389   symbol *retlbl = newiTempLabel(NULL);
3390   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3391   
3392     FENTRY;
3393
3394     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3395     fntype = operandType( IC_LEFT(ic) )->next;
3396
3397     /* if send set is not empty the assign */
3398     if (_G.sendSet) {
3399       iCode *sic;
3400       int psuedoStkPtr=-1; 
3401
3402       /* reverse sendSet if function is not reentrant */
3403       if(!IFFUNC_ISREENT(fntype))
3404         _G.sendSet = reverseSet(_G.sendSet);
3405
3406       stackParms = 0;
3407       
3408       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3409         int size;
3410
3411           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3412           size = AOP_SIZE(IC_LEFT(sic));
3413           stackParms += size;
3414
3415           /* all parameters are passed via stack, since WREG is clobbered
3416            * by the calling sequence */
3417           while (size--) {
3418             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3419             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3420             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3421
3422             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3423             pushw();
3424           }
3425
3426           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3427       }
3428
3429       _G.stackRegSet = _G.sendSet;
3430       _G.sendSet = NULL;
3431     }
3432
3433     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3434
3435     // push return address
3436     // push $ on return stack, then replace with retlbl
3437
3438     /* Thanks to Thorsten Klose for pointing out that the following
3439      * snippet should be interrupt safe */
3440     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3441     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3442
3443     pic16_emitpcodeNULLop(POC_PUSH);
3444
3445     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3446     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3447     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3448     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3449     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3450     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3451
3452
3453     /* restore interrupt control register */
3454     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3455     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3456
3457     /* make the call by writing the pointer into pc */
3458     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3459     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3460
3461     // note: MOVFF to PCL not allowed
3462     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3463     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3464
3465
3466     /* return address is here: (X) */
3467     pic16_emitpLabelFORCE(retlbl->key);
3468
3469     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3470
3471     GpsuedoStkPtr=0;
3472     /* if we need assign a result value */
3473     if ((IS_ITEMP(IC_RESULT(ic))
3474           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3475               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3476         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3477
3478       _G.accInUse++;
3479       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3480       _G.accInUse--;
3481
3482       assignResultValue(IC_RESULT(ic), 1);
3483
3484       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3485               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3486                 
3487       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3488     }
3489
3490 //    stackParms -= use_wreg;
3491     
3492     if(stackParms>0) {
3493       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3494       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3495       if(STACK_MODEL_LARGE) {
3496         emitSKPNC;
3497         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3498       }
3499     }
3500 }
3501
3502 /*-----------------------------------------------------------------*/
3503 /* resultRemat - result  is rematerializable                       */
3504 /*-----------------------------------------------------------------*/
3505 static int resultRemat (iCode *ic)
3506 {
3507   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3508   if (SKIP_IC(ic) || ic->op == IFX)
3509     return 0;
3510
3511   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3512     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3513     if (sym->remat && !POINTER_SET(ic)) 
3514       return 1;
3515   }
3516
3517   return 0;
3518 }
3519
3520 #if defined(__BORLANDC__) || defined(_MSC_VER)
3521 #define STRCASECMP stricmp
3522 #else
3523 #define STRCASECMP strcasecmp
3524 #endif
3525
3526 #if 0
3527 /*-----------------------------------------------------------------*/
3528 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3529 /*-----------------------------------------------------------------*/
3530 static bool inExcludeList(char *s)
3531 {
3532   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3533     int i =0;
3534     
3535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3536     if (options.excludeRegs[i] &&
3537     STRCASECMP(options.excludeRegs[i],"none") == 0)
3538         return FALSE ;
3539
3540     for ( i = 0 ; options.excludeRegs[i]; i++) {
3541         if (options.excludeRegs[i] &&
3542         STRCASECMP(s,options.excludeRegs[i]) == 0)
3543             return TRUE;
3544     }
3545     return FALSE ;
3546 }
3547 #endif
3548
3549 /*-----------------------------------------------------------------*/
3550 /* genFunction - generated code for function entry                 */
3551 /*-----------------------------------------------------------------*/
3552 static void genFunction (iCode *ic)
3553 {
3554   symbol *sym;
3555   sym_link *ftype;
3556   
3557     FENTRY;
3558     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3559
3560     pic16_labelOffset += (max_key+4);
3561     max_key=0;
3562     GpsuedoStkPtr=0;
3563     _G.nRegsSaved = 0;
3564         
3565     ftype = operandType(IC_LEFT(ic));
3566     sym = OP_SYMBOL(IC_LEFT(ic));
3567
3568     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3569       /* create an absolute section at the interrupt vector:
3570        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3571       symbol *asym;
3572       char asymname[128];
3573       pBlock *apb;
3574
3575
3576 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3577
3578 #if 0
3579         {
3580           int i, found=-1;
3581
3582             sym = OP_SYMBOL( IC_LEFT(ic));
3583             for(i=0;i<=2;i++) {
3584               if(interrupts[i]->name
3585                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3586                   found = i;
3587                   break;
3588               }
3589             }
3590                         
3591             if(found == -1) {
3592               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3593                             __FILE__, __LINE__, sym->name);
3594 //              assert( 0 );
3595             }
3596             _G.interruptvector = found;
3597         }
3598 #endif
3599
3600         if(FUNC_INTNO(sym->type) == 256)
3601           sprintf(asymname, "ivec_%s", sym->name);
3602         else
3603           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3604         asym = newSymbol(asymname, 0);
3605
3606         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3607         pic16_addpBlock( apb );
3608
3609         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3610         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3611         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3612                 
3613         /* mark the end of this tiny function */
3614         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3615
3616         {
3617           absSym *abSym;
3618
3619             abSym = Safe_calloc(1, sizeof(absSym));
3620             strcpy(abSym->name, asymname);
3621
3622             switch( FUNC_INTNO(sym->type) ) {
3623               case 0: abSym->address = 0x000000; break;
3624               case 1: abSym->address = 0x000008; break;
3625               case 2: abSym->address = 0x000018; break;
3626               
3627               default:
3628                 abSym->address = -1; break;
3629             }
3630
3631             /* relocate interrupt vectors if needed */
3632             if(abSym->address != -1)
3633               abSym->address += pic16_options.ivt_loc;
3634
3635             addSet(&absSymSet, abSym);
3636         }
3637     }
3638
3639     /* create the function header */
3640     pic16_emitcode(";","-----------------------------------------");
3641     pic16_emitcode(";"," function %s",sym->name);
3642     pic16_emitcode(";","-----------------------------------------");
3643
3644     pic16_emitcode("","%s:",sym->rname);
3645     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3646
3647
3648     {
3649       absSym *ab;
3650
3651         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3652           if(!strcmp(ab->name, sym->rname)) {
3653             pic16_pBlockConvert2Absolute(pb);
3654             break;
3655           }
3656         }
3657     }
3658
3659
3660     if(IFFUNC_ISNAKED(ftype)) {
3661       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3662       return;
3663     }
3664         
3665     /* if critical function then turn interrupts off */
3666     if (IFFUNC_ISCRITICAL(ftype)) {
3667       //pic16_emitcode("clr","ea");
3668     }
3669
3670     _G.fregsUsed = sym->regsUsed;
3671
3672     /* if this is an interrupt service routine then
3673      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3674     if (IFFUNC_ISISR(sym->type)) {
3675         _G.usefastretfie = 1;   /* use shadow registers by default */
3676         
3677         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3678         if(!FUNC_ISSHADOWREGS(sym->type)) {
3679           /* do not save WREG,STATUS,BSR for high priority interrupts
3680            * because they are stored in the hardware shadow registers already */
3681           _G.usefastretfie = 0;
3682           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3683           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3684           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3685         }
3686
3687         /* these should really be optimized somehow, because not all
3688          * interrupt handlers modify them */
3689         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3690         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3691         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3692         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3693         
3694 //        pic16_pBlockConvert2ISR(pb);
3695                 
3696     }
3697
3698     /* emit code to setup stack frame if user enabled,
3699      * and function is not main() */
3700          
3701     //fprintf(stderr, "function name: %s\n", sym->name);
3702     if(strcmp(sym->name, "main")) {
3703       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3704         /* setup the stack frame */
3705         if(STACK_MODEL_LARGE)
3706           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3707         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3708
3709         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3710         if(STACK_MODEL_LARGE)
3711           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3712       }
3713     }
3714
3715     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3716           && sym->stack) {
3717
3718       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3719
3720       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3721       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3722       emitSKPC;
3723       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3724     }
3725           
3726     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3727       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3728         _G.useWreg = 0;
3729       else
3730         _G.useWreg = 1;
3731     } else
3732       _G.useWreg = 0;
3733
3734     /* if callee-save to be used for this function
3735      * then save the registers being used in this function */
3736 //    if (IFFUNC_CALLEESAVES(sym->type))
3737     {
3738       int i;
3739
3740         /* if any registers used */
3741         if (sym->regsUsed) {
3742           /* save the registers used */
3743           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3744           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3745           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3746             if (bitVectBitValue(sym->regsUsed,i)) {
3747               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3748               _G.nRegsSaved++;
3749
3750               if(!pic16_regWithIdx(i)->wasUsed) {
3751                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3752                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3753                 pic16_regWithIdx(i)->wasUsed = 1;
3754               }
3755             }
3756           }
3757           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3758         }
3759     }
3760         
3761     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3762 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3763 }
3764
3765 /*-----------------------------------------------------------------*/
3766 /* genEndFunction - generates epilogue for functions               */
3767 /*-----------------------------------------------------------------*/
3768 static void genEndFunction (iCode *ic)
3769 {
3770   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3771
3772     FENTRY;
3773
3774     if(IFFUNC_ISNAKED(sym->type)) {
3775       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3776       return;
3777     }
3778
3779     _G.stack_lat = 0;
3780
3781     /* add code for ISCRITICAL */
3782     if(IFFUNC_ISCRITICAL(sym->type)) {
3783       /* if critical function, turn on interrupts */
3784       
3785       /* TODO: add code here -- VR */
3786     }
3787     
3788 //    sym->regsUsed = _G.fregsUsed;
3789     
3790     /* now we need to restore the registers */
3791     /* if any registers used */
3792     if (sym->regsUsed) {
3793       int i;
3794
3795         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3796         /* restore registers used */
3797         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3798         for ( i = sym->regsUsed->size; i >= 0; i--) {
3799           if (bitVectBitValue(sym->regsUsed,i)) {
3800             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3801             _G.nRegsSaved--;
3802           }
3803         }
3804         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3805
3806     }
3807
3808     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3809           && sym->stack) {
3810       if (sym->stack == 1) {
3811         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3812         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3813       } else {
3814         // we have to add more than one...
3815         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3816         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3817         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3818         emitSKPNC;
3819         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3820         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3821         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3822       }
3823     }
3824
3825     if(strcmp(sym->name, "main")) {
3826       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3827         /* restore stack frame */
3828         if(STACK_MODEL_LARGE)
3829           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3830         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3831       }
3832     }
3833
3834     _G.useWreg = 0;
3835
3836     if (IFFUNC_ISISR(sym->type)) {
3837       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3838       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3839       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3840       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3841
3842       if(!FUNC_ISSHADOWREGS(sym->type)) {
3843         /* do not restore interrupt vector for WREG,STATUS,BSR
3844          * for high priority interrupt, see genFunction */
3845         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3846         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3847         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3848       }
3849 //      _G.interruptvector = 0;         /* sanity check */
3850
3851
3852       /* if debug then send end of function */
3853 /*      if (options.debug && currFunc)  */
3854       if (currFunc) {
3855         debugFile->writeEndFunction (currFunc, ic, 1);
3856       }
3857         
3858       if(_G.usefastretfie)
3859         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3860       else
3861         pic16_emitpcodeNULLop(POC_RETFIE);
3862
3863       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3864       
3865       _G.usefastretfie = 0;
3866       return;
3867     }
3868
3869     if (IFFUNC_ISCRITICAL(sym->type)) {
3870       pic16_emitcode("setb","ea");
3871     }
3872
3873     /* if debug then send end of function */
3874     if (currFunc) {
3875       debugFile->writeEndFunction (currFunc, ic, 1);
3876     }
3877
3878     /* insert code to restore stack frame, if user enabled it
3879      * and function is not main() */
3880          
3881
3882     pic16_emitpcodeNULLop(POC_RETURN);
3883
3884     /* Mark the end of a function */
3885     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3886 }
3887
3888
3889 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3890 {
3891   if(is_LitOp(op)) {
3892     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3893       if(lit == 0) {
3894         pic16_emitpcode(POC_CLRF, dest);
3895       } else {
3896         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3897         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3898       }
3899   } else {
3900     if(dest->type == PO_WREG && (offset == 0)) {
3901       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3902       return;
3903     }
3904     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3905   }
3906 }
3907
3908 /*-----------------------------------------------------------------*/
3909 /* genRet - generate code for return statement                     */
3910 /*-----------------------------------------------------------------*/
3911 static void genRet (iCode *ic)
3912 {
3913   int size;
3914   operand *left;
3915
3916     FENTRY;
3917         /* if we have no return value then
3918          * just generate the "ret" */
3919         
3920         if (!IC_LEFT(ic)) 
3921                 goto jumpret;       
3922     
3923         /* we have something to return then
3924          * move the return value into place */
3925         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3926         size = AOP_SIZE(IC_LEFT(ic));
3927
3928         if(size <= 4) {
3929                 if(size>3) {
3930                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3931 //                      pic16_emitpcode(POC_MOVFF,
3932 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3933                 }
3934                 if(size>2) {
3935                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3936 //                      pic16_emitpcode(POC_MOVFF,
3937 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3938                 }
3939                 if(size>1) {
3940                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3941 //                      pic16_emitpcode(POC_MOVFF,
3942 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3943                 }
3944
3945 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3946
3947                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3948 //              pic16_emitpcode(POC_MOVFF,
3949 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3950
3951         } else {
3952                 /* >32-bits, setup stack and FSR0 */
3953                 while (size--) {
3954 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3955 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3956
3957                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3958
3959 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3960                         GpsuedoStkPtr++;
3961                 }
3962                         
3963                 /* setup FSR0 */
3964                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3965                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3966
3967                 if(STACK_MODEL_LARGE) {
3968                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3969                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3970                 } else {
3971                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3972                 }
3973         }
3974                                 
3975 #if 0
3976         /* old code, left here for reference -- VR */    
3977         while (size--) {
3978           char *l ;
3979
3980                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3981                         /* #NOCHANGE */
3982                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3983                         pic16_emitpcomment("push %s",l);
3984                         pushed++;
3985                 } else {
3986                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3987                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3988                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3989                         
3990                         if (strcmp(fReturn[offset],l)) {
3991                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3992                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3993                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3994                                 } else {
3995                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3996                                 }
3997                                 
3998                                 if(size) {
3999                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4000                                 }
4001                                 offset++;
4002                         }
4003                 }
4004         }    
4005
4006         if (pushed) {
4007                 while(pushed) {
4008                         pushed--;
4009                         if (strcmp(fReturn[pushed],"a"))
4010                                 pic16_emitcode("pop",fReturn[pushed]);
4011                         else
4012                                 pic16_emitcode("pop","acc");
4013                 }
4014         }
4015 #endif
4016
4017
4018         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4019     
4020 jumpret:
4021         /* generate a jump to the return label
4022          * if the next is not the return statement */
4023         if (!(ic->next && ic->next->op == LABEL
4024                 && IC_LABEL(ic->next) == returnLabel)) {
4025         
4026                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4027                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4028         }
4029 }
4030
4031 /*-----------------------------------------------------------------*/
4032 /* genLabel - generates a label                                    */
4033 /*-----------------------------------------------------------------*/
4034 static void genLabel (iCode *ic)
4035 {
4036   FENTRY;
4037
4038   /* special case never generate */
4039   if (IC_LABEL(ic) == entryLabel)
4040     return ;
4041
4042   pic16_emitpLabel(IC_LABEL(ic)->key);
4043 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4044 }
4045
4046 /*-----------------------------------------------------------------*/
4047 /* genGoto - generates a goto                                      */
4048 /*-----------------------------------------------------------------*/
4049 //tsd
4050 static void genGoto (iCode *ic)
4051 {
4052   FENTRY;
4053   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4054 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4055 }
4056
4057
4058 /*-----------------------------------------------------------------*/
4059 /* genMultbits :- multiplication of bits                           */
4060 /*-----------------------------------------------------------------*/
4061 static void genMultbits (operand *left, 
4062                          operand *right, 
4063                          operand *result)
4064 {
4065   FENTRY;
4066
4067   if(!pic16_sameRegs(AOP(result),AOP(right)))
4068     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4069
4070   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4071   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4072   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4073
4074 }
4075
4076
4077 /*-----------------------------------------------------------------*/
4078 /* genMultOneByte : 8 bit multiplication & division                */
4079 /*-----------------------------------------------------------------*/
4080 static void genMultOneByte (operand *left,
4081                             operand *right,
4082                             operand *result)
4083 {
4084
4085   FENTRY;
4086   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4087   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4088
4089   /* (if two literals, the value is computed before) */
4090   /* if one literal, literal on the right */
4091   if (AOP_TYPE(left) == AOP_LIT){
4092     operand *t = right;
4093     right = left;
4094     left = t;
4095   }
4096
4097         /* size is already checked in genMult == 1 */
4098 //      size = AOP_SIZE(result);
4099
4100         if (AOP_TYPE(right) == AOP_LIT){
4101                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4102                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4103                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4104                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4105         } else {
4106                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4107                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4108                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4109                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4110         }
4111         
4112         pic16_genMult8X8_8 (left, right,result);
4113 }
4114
4115 /*-----------------------------------------------------------------*/
4116 /* genMultOneWord : 16 bit multiplication                          */
4117 /*-----------------------------------------------------------------*/
4118 static void genMultOneWord (operand *left,
4119                             operand *right,
4120                             operand *result)
4121 {
4122   FENTRY;
4123   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4124   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4125
4126   /* (if two literals, the value is computed before)
4127    * if one literal, literal on the right */
4128   if (AOP_TYPE(left) == AOP_LIT){
4129     operand *t = right;
4130     right = left;
4131     left = t;
4132   }
4133
4134   /* size is checked already == 2 */
4135 //  size = AOP_SIZE(result);
4136
4137   if (AOP_TYPE(right) == AOP_LIT) {
4138     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4139       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4140       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4141       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4142   } else {
4143     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4144       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4145       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4146       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4147   }
4148         
4149   pic16_genMult16X16_16(left, right,result);
4150 }
4151
4152 /*-----------------------------------------------------------------*/
4153 /* genMultOneLong : 32 bit multiplication                          */
4154 /*-----------------------------------------------------------------*/
4155 static void genMultOneLong (operand *left,
4156                             operand *right,
4157                             operand *result)
4158 {
4159   FENTRY;
4160   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4161   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4162
4163   /* (if two literals, the value is computed before)
4164    * if one literal, literal on the right */
4165   if (AOP_TYPE(left) == AOP_LIT){
4166     operand *t = right;
4167     right = left;
4168     left = t;
4169   }
4170
4171   /* size is checked already == 4 */
4172 //  size = AOP_SIZE(result);
4173
4174   if (AOP_TYPE(right) == AOP_LIT) {
4175     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4176         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4177         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4178         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4179   } else {
4180     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4181         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4182         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4183         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4184   }
4185         
4186   pic16_genMult32X32_32(left, right,result);
4187 }
4188
4189
4190
4191 /*-----------------------------------------------------------------*/
4192 /* genMult - generates code for multiplication                     */
4193 /*-----------------------------------------------------------------*/
4194 static void genMult (iCode *ic)
4195 {
4196   operand *left = IC_LEFT(ic);
4197   operand *right = IC_RIGHT(ic);
4198   operand *result= IC_RESULT(ic);   
4199
4200     FENTRY;
4201         /* assign the amsops */
4202         pic16_aopOp (left,ic,FALSE);
4203         pic16_aopOp (right,ic,FALSE);
4204         pic16_aopOp (result,ic,TRUE);
4205
4206         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4207
4208         /* special cases first *
4209         * both are bits */
4210         if (AOP_TYPE(left) == AOP_CRY
4211                 && AOP_TYPE(right)== AOP_CRY) {
4212                 genMultbits(left,right,result);
4213           goto release ;
4214         }
4215
4216         /* if both are of size == 1 */
4217         if(AOP_SIZE(left) == 1
4218                 && AOP_SIZE(right) == 1) {
4219                 genMultOneByte(left,right,result);
4220           goto release ;
4221         }
4222
4223         /* if both are of size == 2 */
4224         if(AOP_SIZE(left) == 2
4225                 && AOP_SIZE(right) == 2) {
4226                 genMultOneWord(left, right, result);
4227           goto release;
4228         }
4229         
4230         /* if both are of size == 4 */
4231         if(AOP_SIZE(left) == 4
4232                 && AOP_SIZE(right) == 4) {
4233                 genMultOneLong(left, right, result);
4234           goto release;
4235         }
4236         
4237         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4238
4239
4240         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4241         /* should have been converted to function call */
4242         assert(0) ;
4243
4244 release :
4245         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4246         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4247         pic16_freeAsmop(result,NULL,ic,TRUE); 
4248 }
4249
4250 /*-----------------------------------------------------------------*/
4251 /* genDivbits :- division of bits                                  */
4252 /*-----------------------------------------------------------------*/
4253 static void genDivbits (operand *left, 
4254                         operand *right, 
4255                         operand *result)
4256 {
4257   char *l;
4258
4259     FENTRY;
4260     /* the result must be bit */    
4261     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4262     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4263
4264     MOVA(l);    
4265
4266     pic16_emitcode("div","ab");
4267     pic16_emitcode("rrc","a");
4268     pic16_aopPut(AOP(result),"c",0);
4269 }
4270
4271 /*-----------------------------------------------------------------*/
4272 /* genDivOneByte : 8 bit division                                  */
4273 /*-----------------------------------------------------------------*/
4274 static void genDivOneByte (operand *left,
4275                            operand *right,
4276                            operand *result)
4277 {
4278   sym_link *opetype = operandType(result);
4279   char *l ;
4280   symbol *lbl ;
4281   int size,offset;
4282
4283         /* result = divident / divisor
4284          * - divident may be a register or a literal,
4285          * - divisor may be a register or a literal,
4286          * so there are 3 cases (literal / literal is optimized
4287          * by the front-end) to handle.
4288          * In addition we must handle signed and unsigned, which
4289          * result in 6 final different cases -- VR */
4290
4291     FENTRY;
4292     
4293     size = AOP_SIZE(result) - 1;
4294     offset = 1;
4295     /* signed or unsigned */
4296     if (SPEC_USIGN(opetype)) {
4297       pCodeOp *pct1,    /* count */
4298                 *pct2,  /* reste */
4299                 *pct3;  /* temp */
4300       symbol *label1, *label2, *label3;;
4301
4302
4303         /* unsigned is easy */
4304
4305         pct1 = pic16_popGetTempReg(1);
4306         pct2 = pic16_popGetTempReg(1);
4307         pct3 = pic16_popGetTempReg(1);
4308         
4309         label1 = newiTempLabel(NULL);
4310         label2 = newiTempLabel(NULL);
4311         label3 = newiTempLabel(NULL);
4312
4313         /* the following algorithm is extracted from divuint.c */
4314
4315         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4316         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4317         
4318         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4319
4320         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4321         
4322         pic16_emitpLabel(label1->key);
4323         
4324         emitCLRC;
4325         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4326
4327
4328         emitCLRC;
4329         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4330         
4331
4332         emitSKPNC;
4333         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4334         
4335         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4336         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4337         
4338         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4339         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4340         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4341         
4342         pic16_emitpLabel( label3->key );
4343         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4344         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4345         
4346         
4347
4348         pic16_emitpLabel(label2->key);
4349         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4350         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4351         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4352         
4353         /* result is in wreg */
4354         if(AOP_TYPE(result) != AOP_ACC)
4355                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4356
4357         pic16_popReleaseTempReg( pct3, 1);
4358         pic16_popReleaseTempReg( pct2, 1);
4359         pic16_popReleaseTempReg( pct1, 1);
4360
4361         return ;
4362     }
4363
4364     /* signed is a little bit more difficult */
4365
4366     /* save the signs of the operands */
4367     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4368     MOVA(l);    
4369     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4370     pic16_emitcode("push","acc"); /* save it on the stack */
4371
4372     /* now sign adjust for both left & right */
4373     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4374     MOVA(l);       
4375     lbl = newiTempLabel(NULL);
4376     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4377     pic16_emitcode("cpl","a");   
4378     pic16_emitcode("inc","a");
4379     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4380     pic16_emitcode("mov","b,a");
4381
4382     /* sign adjust left side */
4383     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4384     MOVA(l);
4385
4386     lbl = newiTempLabel(NULL);
4387     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4388     pic16_emitcode("cpl","a");
4389     pic16_emitcode("inc","a");
4390     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4391
4392     /* now the division */
4393     pic16_emitcode("div","ab");
4394     /* we are interested in the lower order
4395     only */
4396     pic16_emitcode("mov","b,a");
4397     lbl = newiTempLabel(NULL);
4398     pic16_emitcode("pop","acc");   
4399     /* if there was an over flow we don't 
4400     adjust the sign of the result */
4401     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4402     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4403     CLRC;
4404     pic16_emitcode("clr","a");
4405     pic16_emitcode("subb","a,b");
4406     pic16_emitcode("mov","b,a");
4407     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4408
4409     /* now we are done */
4410     pic16_aopPut(AOP(result),"b",0);
4411     if(size > 0){
4412         pic16_emitcode("mov","c,b.7");
4413         pic16_emitcode("subb","a,acc");   
4414     }
4415     while (size--)
4416         pic16_aopPut(AOP(result),"a",offset++);
4417
4418 }
4419
4420 /*-----------------------------------------------------------------*/
4421 /* genDiv - generates code for division                            */
4422 /*-----------------------------------------------------------------*/
4423 static void genDiv (iCode *ic)
4424 {
4425     operand *left = IC_LEFT(ic);
4426     operand *right = IC_RIGHT(ic);
4427     operand *result= IC_RESULT(ic);   
4428
4429
4430         /* Division is a very lengthy algorithm, so it is better
4431          * to call support routines than inlining algorithm.
4432          * Division functions written here just in case someone
4433          * wants to inline and not use the support libraries -- VR */
4434
4435     FENTRY;
4436     
4437     /* assign the amsops */
4438     pic16_aopOp (left,ic,FALSE);
4439     pic16_aopOp (right,ic,FALSE);
4440     pic16_aopOp (result,ic,TRUE);
4441
4442     /* special cases first */
4443     /* both are bits */
4444     if (AOP_TYPE(left) == AOP_CRY &&
4445         AOP_TYPE(right)== AOP_CRY) {
4446         genDivbits(left,right,result);
4447         goto release ;
4448     }
4449
4450     /* if both are of size == 1 */
4451     if (AOP_SIZE(left) == 1 &&
4452         AOP_SIZE(right) == 1 ) {
4453         genDivOneByte(left,right,result);
4454         goto release ;
4455     }
4456
4457     /* should have been converted to function call */
4458     assert(0);
4459 release :
4460     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4461     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4462     pic16_freeAsmop(result,NULL,ic,TRUE); 
4463 }
4464
4465 /*-----------------------------------------------------------------*/
4466 /* genModbits :- modulus of bits                                   */
4467 /*-----------------------------------------------------------------*/
4468 static void genModbits (operand *left, 
4469                         operand *right, 
4470                         operand *result)
4471 {
4472   char *l;
4473
4474     FENTRY;  
4475     
4476     werror(W_POSSBUG2, __FILE__, __LINE__);
4477     /* the result must be bit */    
4478     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4479     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4480
4481     MOVA(l);       
4482
4483     pic16_emitcode("div","ab");
4484     pic16_emitcode("mov","a,b");
4485     pic16_emitcode("rrc","a");
4486     pic16_aopPut(AOP(result),"c",0);
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* genModOneByte : 8 bit modulus                                   */
4491 /*-----------------------------------------------------------------*/
4492 static void genModOneByte (operand *left,
4493                            operand *right,
4494                            operand *result)
4495 {
4496   sym_link *opetype = operandType(result);
4497   char *l ;
4498   symbol *lbl ;
4499
4500     FENTRY;
4501     werror(W_POSSBUG2, __FILE__, __LINE__);
4502
4503     /* signed or unsigned */
4504     if (SPEC_USIGN(opetype)) {
4505         /* unsigned is easy */
4506         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4507         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4508         MOVA(l);    
4509         pic16_emitcode("div","ab");
4510         pic16_aopPut(AOP(result),"b",0);
4511         return ;
4512     }
4513
4514     /* signed is a little bit more difficult */
4515
4516     /* save the signs of the operands */
4517     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4518     MOVA(l);
4519
4520     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4521     pic16_emitcode("push","acc"); /* save it on the stack */
4522
4523     /* now sign adjust for both left & right */
4524     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4525     MOVA(l);
4526
4527     lbl = newiTempLabel(NULL);
4528     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4529     pic16_emitcode("cpl","a");   
4530     pic16_emitcode("inc","a");
4531     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4532     pic16_emitcode("mov","b,a"); 
4533
4534     /* sign adjust left side */
4535     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4536     MOVA(l);
4537
4538     lbl = newiTempLabel(NULL);
4539     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4540     pic16_emitcode("cpl","a");   
4541     pic16_emitcode("inc","a");
4542     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4543
4544     /* now the multiplication */
4545     pic16_emitcode("div","ab");
4546     /* we are interested in the lower order
4547     only */
4548     lbl = newiTempLabel(NULL);
4549     pic16_emitcode("pop","acc");   
4550     /* if there was an over flow we don't 
4551     adjust the sign of the result */
4552     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4553     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4554     CLRC ;
4555     pic16_emitcode("clr","a");
4556     pic16_emitcode("subb","a,b");
4557     pic16_emitcode("mov","b,a");
4558     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4559
4560     /* now we are done */
4561     pic16_aopPut(AOP(result),"b",0);
4562
4563 }
4564
4565 /*-----------------------------------------------------------------*/
4566 /* genMod - generates code for division                            */
4567 /*-----------------------------------------------------------------*/
4568 static void genMod (iCode *ic)
4569 {
4570   operand *left = IC_LEFT(ic);
4571   operand *right = IC_RIGHT(ic);
4572   operand *result= IC_RESULT(ic);  
4573
4574     FENTRY;
4575     
4576     /* assign the amsops */
4577     pic16_aopOp (left,ic,FALSE);
4578     pic16_aopOp (right,ic,FALSE);
4579     pic16_aopOp (result,ic,TRUE);
4580
4581     /* special cases first */
4582     /* both are bits */
4583     if (AOP_TYPE(left) == AOP_CRY &&
4584         AOP_TYPE(right)== AOP_CRY) {
4585         genModbits(left,right,result);
4586         goto release ;
4587     }
4588
4589     /* if both are of size == 1 */
4590     if (AOP_SIZE(left) == 1 &&
4591         AOP_SIZE(right) == 1 ) {
4592         genModOneByte(left,right,result);
4593         goto release ;
4594     }
4595
4596     /* should have been converted to function call */
4597     assert(0);
4598
4599 release :
4600     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4601     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4602     pic16_freeAsmop(result,NULL,ic,TRUE); 
4603 }
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genIfxJump :- will create a jump depending on the ifx           */
4607 /*-----------------------------------------------------------------*/
4608 /*
4609   note: May need to add parameter to indicate when a variable is in bit space.
4610 */
4611 static void genIfxJump (iCode *ic, char *jval)
4612 {
4613   FENTRY;
4614   
4615     /* if true label then we jump if condition
4616     supplied is true */
4617     if ( IC_TRUE(ic) ) {
4618
4619         if(strcmp(jval,"a") == 0)
4620           emitSKPZ;
4621         else if (strcmp(jval,"c") == 0)
4622           emitSKPNC;
4623         else {
4624           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4625           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4626         }
4627
4628         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4629         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4630
4631     }
4632     else {
4633         /* false label is present */
4634         if(strcmp(jval,"a") == 0)
4635           emitSKPNZ;
4636         else if (strcmp(jval,"c") == 0)
4637           emitSKPC;
4638         else {
4639           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4640           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4641         }
4642
4643         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4644         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4645
4646     }
4647
4648
4649     /* mark the icode as generated */
4650     ic->generated = 1;
4651 }
4652
4653 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4654 {
4655   FENTRY;
4656   
4657     /* if true label then we jump if condition
4658     supplied is true */
4659     if ( IC_TRUE(ic) ) {
4660       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4661       pic16_emitpcode(POC_BTFSC, jop);
4662
4663       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4664       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4665
4666     } else {
4667       /* false label is present */
4668       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4669       pic16_emitpcode(POC_BTFSS, jop);
4670           
4671       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4672       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4673     }
4674
4675
4676     /* mark the icode as generated */
4677     ic->generated = 1;
4678 }
4679
4680 #if 0
4681 // not needed ATM
4682
4683 /*-----------------------------------------------------------------*/
4684 /* genSkip                                                         */
4685 /*-----------------------------------------------------------------*/
4686 static void genSkip(iCode *ifx,int status_bit)
4687 {
4688   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4689   if(!ifx)
4690     return;
4691
4692   if ( IC_TRUE(ifx) ) {
4693     switch(status_bit) {
4694     case 'z':
4695       emitSKPNZ;
4696       break;
4697
4698     case 'c':
4699       emitSKPNC;
4700       break;
4701
4702     case 'd':
4703       emitSKPDC;
4704       break;
4705
4706     }
4707
4708     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4709     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4710
4711   } else {
4712
4713     switch(status_bit) {
4714
4715     case 'z':
4716       emitSKPZ;
4717       break;
4718
4719     case 'c':
4720       emitSKPC;
4721       break;
4722
4723     case 'd':
4724       emitSKPDC;
4725       break;
4726     }
4727     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4728     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4729
4730   }
4731
4732 }
4733 #endif
4734
4735 /*-----------------------------------------------------------------*/
4736 /* genSkipc                                                        */
4737 /*-----------------------------------------------------------------*/
4738 static void genSkipc(resolvedIfx *rifx)
4739 {
4740   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4741   
4742   if(!rifx)
4743     return;
4744
4745   if(rifx->condition)
4746     emitSKPC;
4747   else
4748     emitSKPNC;
4749
4750   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4751   rifx->generated = 1;
4752 }
4753
4754 #if !(USE_SIMPLE_GENCMP)
4755 /*-----------------------------------------------------------------*/
4756 /* genSkipz2                                                       */
4757 /*-----------------------------------------------------------------*/
4758 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4759 {
4760   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4761   
4762   if(!rifx)
4763     return;
4764
4765   if( (rifx->condition ^ invert_condition) & 1)
4766     emitSKPZ;
4767   else
4768     emitSKPNZ;
4769
4770   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4771   rifx->generated = 1;
4772 }
4773 #endif
4774
4775 #if 0
4776 /*-----------------------------------------------------------------*/
4777 /* genSkipz                                                        */
4778 /*-----------------------------------------------------------------*/
4779 static void genSkipz(iCode *ifx, int condition)
4780 {
4781   if(!ifx)
4782     return;
4783
4784   if(condition)
4785     emitSKPNZ;
4786   else
4787     emitSKPZ;
4788
4789   if ( IC_TRUE(ifx) )
4790     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4791   else
4792     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4793
4794   if ( IC_TRUE(ifx) )
4795     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4796   else
4797     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4798
4799 }
4800 #endif
4801
4802 #if !(USE_SIMPLE_GENCMP)
4803 /*-----------------------------------------------------------------*/
4804 /* genSkipCond                                                     */
4805 /*-----------------------------------------------------------------*/
4806 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4807 {
4808   if(!rifx)
4809     return;
4810
4811   if(rifx->condition)
4812     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4813   else
4814     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4815
4816
4817   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4818   rifx->generated = 1;
4819 }
4820 #endif
4821
4822 #if 0
4823 /*-----------------------------------------------------------------*/
4824 /* genChkZeroes :- greater or less than comparison                 */
4825 /*     For each byte in a literal that is zero, inclusive or the   */
4826 /*     the corresponding byte in the operand with W                */
4827 /*     returns true if any of the bytes are zero                   */
4828 /*-----------------------------------------------------------------*/
4829 static int genChkZeroes(operand *op, int lit,  int size)
4830 {
4831
4832   int i;
4833   int flag =1;
4834
4835   while(size--) {
4836     i = (lit >> (size*8)) & 0xff;
4837
4838     if(i==0) {
4839       if(flag) 
4840         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4841       else
4842         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4843       flag = 0;
4844     }
4845   }
4846
4847   return (flag==0);
4848 }
4849 #endif
4850
4851 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4852 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4853 #endif
4854 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4855 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4856
4857 /*-----------------------------------------------------------------*/
4858 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4859 /*                  aop (if it's NOT a literal) or from lit (if    */
4860 /*                  aop is a literal)                              */
4861 /*-----------------------------------------------------------------*/
4862 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4863   if (aop->type == AOP_LIT) {
4864     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4865   } else {
4866     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4867   }
4868 }
4869
4870 /*-----------------------------------------------------------------*/
4871 /* genCmp :- greater or less than comparison                       */
4872 /*-----------------------------------------------------------------*/
4873
4874 #if USE_SIMPLE_GENCMP
4875
4876 /* genCmp performs a left < right comparison, stores
4877  * the outcome in result (if != NULL) and generates
4878  * control flow code for the ifx (if != NULL).
4879  *
4880  * This version leaves in sequences like
4881  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4882  * which should be optmized by the peephole
4883  * optimizer - RN 2005-01-01 */
4884 static void genCmp (operand *left,operand *right,
4885                     operand *result, iCode *ifx, int sign)
4886 {
4887   resolvedIfx rIfx;
4888   int size;
4889   int offs;
4890   symbol *templbl;
4891   operand *dummy;
4892   unsigned long lit;
4893   unsigned long mask;
4894   int performedLt;
4895
4896   FENTRY;
4897   
4898   assert (AOP_SIZE(left) == AOP_SIZE(right));
4899   assert (left && right);
4900
4901   size = AOP_SIZE(right) - 1;
4902   mask = (0x100UL << (size*8)) - 1;
4903   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4904   performedLt = 1;
4905   templbl = NULL;
4906   lit = 0;
4907   
4908   resolveIfx (&rIfx, ifx);
4909
4910   /**********************************************************************
4911    * handle bits - bit compares are promoted to int compares seemingly! *
4912    **********************************************************************/
4913 #if 0
4914   // THIS IS COMPLETELY UNTESTED!
4915   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4916     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4917     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4918     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4919
4920     emitSETC;
4921     // 1 < {0,1} is false --> clear C by skipping the next instruction
4922     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4923     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4924     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4925     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4926     emitCLRC; // only skipped for left=0 && right=1
4927
4928     goto correct_result_in_carry;
4929   } // if
4930 #endif
4931
4932   /*************************************************
4933    * make sure that left is register (or the like) *
4934    *************************************************/
4935   if (!isAOP_REGlike(left)) {
4936     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4937     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4938     #endif
4939     assert (isAOP_LIT(left));
4940     assert (isAOP_REGlike(right));
4941     // swap left and right
4942     // left < right <==> right > left <==> (right >= left + 1)
4943     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4944
4945     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4946       // MAXVALUE < right? always false
4947       if (performedLt) emitCLRC; else emitSETC;
4948       goto correct_result_in_carry;
4949     } // if
4950
4951     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4952     // that's we handled it above.
4953     lit++;
4954
4955     dummy = left;
4956     left = right;
4957     right = dummy;
4958
4959     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4960   } else if (isAOP_LIT(right)) {
4961     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4962   } // if
4963
4964   assert (isAOP_REGlike(left)); // left must be register or the like
4965   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4966
4967   /*************************************************
4968    * special cases go here                         *
4969    *************************************************/
4970
4971   if (isAOP_LIT(right)) {
4972     if (!sign) {
4973       // unsigned comparison to a literal
4974       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4975       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4976       #endif
4977       if (lit == 0) {
4978         // unsigned left < 0? always false
4979         if (performedLt) emitCLRC; else emitSETC;
4980         goto correct_result_in_carry;
4981       }
4982     } else {
4983       // signed comparison to a literal
4984       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4985       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4986       #endif
4987       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4988         // signed left < 0x80000000? always false
4989         if (performedLt) emitCLRC; else emitSETC;
4990         goto correct_result_in_carry;
4991       } else if (lit == 0) {
4992         // compare left < 0; set CARRY if SIGNBIT(left) is set
4993         if (performedLt) emitSETC; else emitCLRC;
4994         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4995         if (performedLt) emitCLRC; else emitSETC;
4996         goto correct_result_in_carry;
4997       }
4998     } // if (!sign)
4999   } // right is literal
5000
5001   /*************************************************
5002    * perform a general case comparison             *
5003    * make sure we get CARRY==1 <==> left >= right  *
5004    *************************************************/
5005   // compare most significant bytes
5006   //DEBUGpc ("comparing bytes at offset %d", size);
5007   if (!sign) {
5008     // unsigned comparison
5009     mov2w_regOrLit (AOP(right), lit, size);
5010     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5011   } else {
5012     // signed comparison
5013     // (add 2^n to both operands then perform an unsigned comparison)
5014     if (isAOP_LIT(right)) {
5015       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5016       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5017
5018       if (litbyte == 0x80) {
5019         // left >= 0x80 -- always true, but more bytes to come
5020         pic16_mov2w (AOP(left), size);
5021         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5022         emitSETC;
5023       } else {
5024         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5025         pic16_mov2w (AOP(left), size);
5026         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5027         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5028       } // if
5029     } else {
5030       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5031       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5032       pic16_mov2w (AOP(left), size);
5033       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5034       pic16_emitpcode (POC_MOVWF, pctemp);
5035       pic16_mov2w (AOP(right), size);
5036       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5037       pic16_emitpcode (POC_SUBFW, pctemp);
5038       //pic16_popReleaseTempReg(pctemp, 1);
5039     }
5040   } // if (!sign)
5041
5042   // compare remaining bytes (treat as unsigned case from above)
5043   templbl = newiTempLabel ( NULL );
5044   offs = size;
5045   while (offs--) {
5046     //DEBUGpc ("comparing bytes at offset %d", offs);
5047     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5048     mov2w_regOrLit (AOP(right), lit, offs);
5049     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5050   } // while (offs)
5051   pic16_emitpLabel (templbl->key);
5052   goto result_in_carry;
5053
5054 result_in_carry:
5055   
5056   /****************************************************
5057    * now CARRY contains the result of the comparison: *
5058    * SUBWF sets CARRY iff                             *
5059    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5060    * (F=left, W=right)
5061    ****************************************************/
5062
5063   if (performedLt) {
5064     if (result && AOP_TYPE(result) != AOP_CRY) {
5065       // value will be stored
5066       emitTOGC;
5067     } else {
5068       // value wil only be used in the following genSkipc()
5069       rIfx.condition ^= 1;
5070     }
5071   } // if
5072
5073 correct_result_in_carry:
5074
5075   // assign result to variable (if neccessary)
5076   if (result && AOP_TYPE(result) != AOP_CRY) {
5077     //DEBUGpc ("assign result");
5078     size = AOP_SIZE(result);
5079     while (size--) {
5080       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5081     } // while
5082     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5083   } // if (result)
5084
5085   // perform conditional jump
5086   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5087   if (ifx) {
5088     //DEBUGpc ("generate control flow");
5089     rIfx.condition ^= 1;
5090     genSkipc (&rIfx);
5091     ifx->generated = 1;
5092   } // if
5093 }
5094
5095 #elif 1
5096                 /* { */
5097       /* original code */
5098 static void genCmp (operand *left,operand *right,
5099                     operand *result, iCode *ifx, int sign)
5100 {
5101   int size; //, offset = 0 ;
5102   unsigned long lit = 0L,i = 0;
5103   resolvedIfx rFalseIfx;
5104   //  resolvedIfx rTrueIfx;
5105   symbol *truelbl;
5106   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5107 /*
5108   if(ifx) {
5109     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5110     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5111   }
5112 */
5113
5114   FENTRY;
5115   
5116   resolveIfx(&rFalseIfx,ifx);
5117   truelbl  = newiTempLabel(NULL);
5118   size = max(AOP_SIZE(left),AOP_SIZE(right));
5119
5120   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5121
5122 #define _swapp
5123
5124   /* if literal is on the right then swap with left */
5125   if ((AOP_TYPE(right) == AOP_LIT)) {
5126     operand *tmp = right ;
5127     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5128     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5129 #ifdef _swapp
5130
5131     lit = (lit - 1) & mask;
5132     right = left;
5133     left = tmp;
5134     rFalseIfx.condition ^= 1;
5135 #endif
5136
5137   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5138     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5139   }
5140
5141
5142   //if(IC_TRUE(ifx) == NULL)
5143   /* if left & right are bit variables */
5144   if (AOP_TYPE(left) == AOP_CRY &&
5145       AOP_TYPE(right) == AOP_CRY ) {
5146     assert (0 && "bit variables used in genCmp");
5147     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5148     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5149   } else {
5150     /* subtract right from left if at the
5151        end the carry flag is set then we know that
5152        left is greater than right */
5153
5154     symbol *lbl  = newiTempLabel(NULL);
5155
5156 #if 0
5157         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5158                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5159 #endif
5160
5161 #ifndef _swapp
5162     if(AOP_TYPE(right) == AOP_LIT) {
5163
5164       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5165
5166       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5167
5168       /* special cases */
5169
5170       if(lit == 0) {
5171
5172         if(sign != 0) 
5173           genSkipCond(&rFalseIfx,left,size-1,7);
5174         else 
5175           /* no need to compare to 0...*/
5176           /* NOTE: this is a de-generate compare that most certainly 
5177            *       creates some dead code. */
5178           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5179
5180         if(ifx) ifx->generated = 1;
5181         return;
5182
5183       }
5184       size--;
5185
5186       if(size == 0) {
5187         //i = (lit >> (size*8)) & 0xff;
5188         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5189         
5190         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5191
5192         i = ((0-lit) & 0xff);
5193         if(sign) {
5194           if( i == 0x81) { 
5195             /* lit is 0x7f, all signed chars are less than
5196              * this except for 0x7f itself */
5197             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5198             genSkipz2(&rFalseIfx,0);
5199           } else {
5200             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5201             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5202             genSkipc(&rFalseIfx);
5203           }
5204
5205         } else {
5206           if(lit == 1) {
5207             genSkipz2(&rFalseIfx,1);
5208           } else {
5209             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5210             genSkipc(&rFalseIfx);
5211           }
5212         }
5213
5214         if(ifx) ifx->generated = 1;
5215         return;
5216       }
5217
5218       /* chars are out of the way. now do ints and longs */
5219
5220
5221       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5222         
5223       /* special cases */
5224
5225       if(sign) {
5226
5227         if(lit == 0) {
5228           genSkipCond(&rFalseIfx,left,size,7);
5229           if(ifx) ifx->generated = 1;
5230           return;
5231         }
5232
5233         if(lit <0x100) {
5234           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5235
5236           //rFalseIfx.condition ^= 1;
5237           //genSkipCond(&rFalseIfx,left,size,7);
5238           //rFalseIfx.condition ^= 1;
5239
5240           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5241           if(rFalseIfx.condition)
5242             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5243           else
5244             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5245
5246           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5247           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5248           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5249
5250           while(size > 1)
5251             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5252
5253           if(rFalseIfx.condition) {
5254             emitSKPZ;
5255             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5256
5257           } else {
5258             emitSKPNZ;
5259           }
5260
5261           genSkipc(&rFalseIfx);
5262           pic16_emitpLabel(truelbl->key);
5263           if(ifx) ifx->generated = 1;
5264           return;
5265
5266         }
5267
5268         if(size == 1) {
5269
5270           if( (lit & 0xff) == 0) {
5271             /* lower byte is zero */
5272             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5273             i = ((lit >> 8) & 0xff) ^0x80;
5274             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5275             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5276             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5277             genSkipc(&rFalseIfx);
5278
5279
5280             if(ifx) ifx->generated = 1;
5281             return;
5282
5283           }
5284         } else {
5285           /* Special cases for signed longs */
5286           if( (lit & 0xffffff) == 0) {
5287             /* lower byte is zero */
5288             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5289             i = ((lit >> 8*3) & 0xff) ^0x80;
5290             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5292             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5293             genSkipc(&rFalseIfx);
5294
5295
5296             if(ifx) ifx->generated = 1;
5297             return;
5298
5299           }
5300
5301         }
5302
5303
5304         if(lit & (0x80 << (size*8))) {
5305           /* lit is negative */
5306           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5307
5308           //genSkipCond(&rFalseIfx,left,size,7);
5309
5310           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5311
5312           if(rFalseIfx.condition)
5313             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5314           else
5315             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5316
5317
5318         } else {
5319           /* lit is positive */
5320           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5321           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5322           if(rFalseIfx.condition)
5323             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5324           else
5325             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5326
5327         }
5328
5329         /*
5330           This works, but is only good for ints.
5331           It also requires a "known zero" register.
5332           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5333           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5334           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5335           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5336           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5337           genSkipc(&rFalseIfx);
5338
5339           pic16_emitpLabel(truelbl->key);
5340           if(ifx) ifx->generated = 1;
5341           return;
5342         **/
5343           
5344         /* There are no more special cases, so perform a general compare */
5345   
5346         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5347         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5348
5349         while(size--) {
5350
5351           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5352           emitSKPNZ;
5353           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5354         }
5355         //rFalseIfx.condition ^= 1;
5356         genSkipc(&rFalseIfx);
5357
5358         pic16_emitpLabel(truelbl->key);
5359
5360         if(ifx) ifx->generated = 1;
5361         return;
5362
5363
5364       }
5365
5366
5367       /* sign is out of the way. So now do an unsigned compare */
5368       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5369
5370
5371       /* General case - compare to an unsigned literal on the right.*/
5372
5373       i = (lit >> (size*8)) & 0xff;
5374       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5375       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5376       while(size--) {
5377         i = (lit >> (size*8)) & 0xff;
5378
5379         if(i) {
5380           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5381           emitSKPNZ;
5382           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5383         } else {
5384           /* this byte of the lit is zero, 
5385            *if it's not the last then OR in the variable */
5386           if(size)
5387             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5388         }
5389       }
5390
5391
5392       pic16_emitpLabel(lbl->key);
5393 //      pic16_emitpLabel(truelbl->key);
5394       //if(emitFinalCheck)
5395       genSkipc(&rFalseIfx);
5396       if(sign)
5397         pic16_emitpLabel(truelbl->key);
5398
5399       if(ifx) ifx->generated = 1;
5400       return;
5401
5402
5403     }
5404 #endif  // _swapp
5405
5406     if(AOP_TYPE(left) == AOP_LIT) {
5407       //symbol *lbl = newiTempLabel(NULL);
5408
5409       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5410
5411
5412       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5413
5414       /* Special cases */
5415       if((lit == 0) && (sign == 0)){
5416
5417         size--;
5418         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5419         while(size) 
5420           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5421
5422         genSkipz2(&rFalseIfx,0);
5423         if(ifx) ifx->generated = 1;
5424         return;
5425       }
5426
5427       if(size==1) {
5428         /* Special cases */
5429         lit &= 0xff;
5430         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5431           /* degenerate compare can never be true */
5432           if(rFalseIfx.condition == 0)
5433             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5434
5435           if(ifx) ifx->generated = 1;
5436           return;
5437         }
5438
5439         if(sign) {
5440           /* signed comparisons to a literal byte */
5441
5442           int lp1 = (lit+1) & 0xff;
5443
5444           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5445           switch (lp1) {
5446           case 0:
5447             rFalseIfx.condition ^= 1;
5448             genSkipCond(&rFalseIfx,right,0,7);
5449             break;
5450           case 0x7f:
5451             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5452             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5453             genSkipz2(&rFalseIfx,1);
5454             break;
5455           default:
5456             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5457             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5458             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5459             rFalseIfx.condition ^= 1;
5460             genSkipc(&rFalseIfx);
5461             break;
5462           }
5463         } else {
5464           /* unsigned comparisons to a literal byte */
5465
5466           switch(lit & 0xff ) {
5467           case 0:
5468             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5469             genSkipz2(&rFalseIfx,0);
5470             break;
5471           case 0x7f:
5472             rFalseIfx.condition ^= 1;
5473             genSkipCond(&rFalseIfx,right,0,7);
5474             break;
5475
5476           default:
5477             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5478             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5479             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5480             rFalseIfx.condition ^= 1;
5481             if (AOP_TYPE(result) == AOP_CRY)
5482               genSkipc(&rFalseIfx);
5483             else {
5484               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5485               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5486             }         
5487             break;
5488           }
5489         }
5490
5491         if(ifx) ifx->generated = 1;
5492         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5493                 goto check_carry;
5494         return;
5495
5496       } else {
5497
5498         /* Size is greater than 1 */
5499
5500         if(sign) {
5501           int lp1 = lit+1;
5502
5503           size--;
5504
5505           if(lp1 == 0) {
5506             /* this means lit = 0xffffffff, or -1 */
5507
5508
5509             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5510             rFalseIfx.condition ^= 1;
5511             genSkipCond(&rFalseIfx,right,size,7);
5512             if(ifx) ifx->generated = 1;
5513
5514             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5515               goto check_carry;
5516
5517             return;
5518           }
5519
5520           if(lit == 0) {
5521             int s = size;
5522
5523             if(rFalseIfx.condition) {
5524               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5525               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5526             }
5527
5528             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5529             while(size--)
5530               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5531
5532
5533             emitSKPZ;
5534             if(rFalseIfx.condition) {
5535               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5536               pic16_emitpLabel(truelbl->key);
5537             }else {
5538               rFalseIfx.condition ^= 1;
5539               genSkipCond(&rFalseIfx,right,s,7);
5540             }
5541
5542             if(ifx) ifx->generated = 1;
5543
5544             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5545               goto check_carry;
5546
5547             return;
5548           }
5549
5550           if((size == 1) &&  (0 == (lp1&0xff))) {
5551             /* lower byte of signed word is zero */
5552             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5553             i = ((lp1 >> 8) & 0xff) ^0x80;
5554             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5555             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5557
5558             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5559               emitTOGC;
5560               if(ifx) ifx->generated = 1;
5561               goto check_carry;
5562             } else {
5563               rFalseIfx.condition ^= 1;
5564               genSkipc(&rFalseIfx);
5565               if(ifx) ifx->generated = 1;
5566             }
5567
5568             return;
5569           }
5570
5571           if(lit & (0x80 << (size*8))) {
5572             /* Lit is less than zero */
5573             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5574             //rFalseIfx.condition ^= 1;
5575             //genSkipCond(&rFalseIfx,left,size,7);
5576             //rFalseIfx.condition ^= 1;
5577             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5578             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5579
5580             if(rFalseIfx.condition)
5581               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5582             else
5583               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5584
5585
5586           } else {
5587             /* Lit is greater than or equal to zero */
5588             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5589             //rFalseIfx.condition ^= 1;
5590             //genSkipCond(&rFalseIfx,right,size,7);
5591             //rFalseIfx.condition ^= 1;
5592
5593             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5594             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5595
5596             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5597             if(rFalseIfx.condition)
5598               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5599             else
5600               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5601
5602           }
5603
5604           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5605           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5606
5607           while(size--) {
5608
5609             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5610             emitSKPNZ;
5611             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5612           }
5613           rFalseIfx.condition ^= 1;
5614           //rFalseIfx.condition = 1;
5615           genSkipc(&rFalseIfx);
5616
5617           pic16_emitpLabel(truelbl->key);
5618
5619           if(ifx) ifx->generated = 1;
5620
5621
5622           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5623             goto check_carry;
5624
5625           return;
5626           // end of if (sign)
5627         } else {
5628
5629           /* compare word or long to an unsigned literal on the right.*/
5630
5631
5632           size--;
5633           if(lit < 0xff) {
5634             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5635             switch (lit) {
5636             case 0:
5637               break; /* handled above */
5638 /*
5639             case 0xff:
5640               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5641               while(size--)
5642                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5643               genSkipz2(&rFalseIfx,0);
5644               break;
5645 */
5646             default:
5647               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5648               while(--size)
5649                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5650
5651               emitSKPZ;
5652               if(rFalseIfx.condition)
5653                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5654               else
5655                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5656
5657
5658               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5659               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5660
5661               rFalseIfx.condition ^= 1;
5662               genSkipc(&rFalseIfx);
5663             }
5664
5665             pic16_emitpLabel(truelbl->key);
5666
5667             if(ifx) ifx->generated = 1;
5668
5669             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5670               goto check_carry;
5671
5672             return;
5673           }
5674
5675
5676           lit++;
5677           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5678           i = (lit >> (size*8)) & 0xff;
5679
5680           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5681           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5682
5683           while(size--) {
5684             i = (lit >> (size*8)) & 0xff;
5685
5686             if(i) {
5687               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5688               emitSKPNZ;
5689               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5690             } else {
5691               /* this byte of the lit is zero, 
5692                * if it's not the last then OR in the variable */
5693               if(size)
5694                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5695             }
5696           }
5697
5698
5699           pic16_emitpLabel(lbl->key);
5700
5701           rFalseIfx.condition ^= 1;
5702
5703           genSkipc(&rFalseIfx);
5704         }
5705
5706         if(sign)
5707           pic16_emitpLabel(truelbl->key);
5708         if(ifx) ifx->generated = 1;
5709
5710             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5711               goto check_carry;
5712
5713         return;
5714       }
5715     }
5716     /* Compare two variables */
5717
5718     DEBUGpic16_emitcode(";sign","%d",sign);
5719
5720     size--;
5721     if(sign) {
5722       /* Sigh. thus sucks... */
5723       if(size) {
5724         pCodeOp *pctemp;
5725         
5726         pctemp = pic16_popGetTempReg(1);
5727         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5728         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5729         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5730         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5731         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5732         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5733         pic16_popReleaseTempReg(pctemp, 1);
5734       } else {
5735         /* Signed char comparison */
5736         /* Special thanks to Nikolai Golovchenko for this snippet */
5737         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5738         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5739         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5741         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5742         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5743
5744         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5745         genSkipc(&rFalseIfx);
5746           
5747         if(ifx) ifx->generated = 1;
5748
5749             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5750               goto check_carry;
5751
5752         return;
5753       }
5754
5755     } else {
5756
5757       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5758       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5759     }
5760
5761
5762     /* The rest of the bytes of a multi-byte compare */
5763     while (size) {
5764
5765       emitSKPZ;
5766       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5767       size--;
5768
5769       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5770       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5771
5772
5773     }
5774
5775     pic16_emitpLabel(lbl->key);
5776
5777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5778     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5779         (AOP_TYPE(result) == AOP_REG)) {
5780       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5781       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5782     } else {
5783       genSkipc(&rFalseIfx);
5784     }         
5785     //genSkipc(&rFalseIfx);
5786     if(ifx) ifx->generated = 1;
5787
5788
5789             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5790               goto check_carry;
5791
5792     return;
5793
5794   }
5795
5796 check_carry:
5797   if ((AOP_TYPE(result) != AOP_CRY) 
5798         && AOP_SIZE(result)) {
5799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5800
5801     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5802
5803     pic16_outBitC(result);
5804   } else {
5805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5806     /* if the result is used in the next
5807        ifx conditional branch then generate
5808        code a little differently */
5809     if (ifx )
5810       genIfxJump (ifx,"c");
5811     else
5812       pic16_outBitC(result);
5813     /* leave the result in acc */
5814   }
5815
5816 }
5817
5818 #else   /* old version of genCmp() */   /* } else { */
5819
5820 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5821 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5822         operand *result, int offset, int invert_op)
5823 {
5824   /* add code here */
5825   
5826   /* check condition, > or < ?? */
5827   if(rIfx->condition != 0)invert_op ^= 1;
5828   
5829   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5830
5831   if(!ifx)invert_op ^= 1;
5832
5833   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5834       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5835   
5836   /* do selection */
5837   if(!invert_op)return POC_CPFSGT;
5838   else return POC_CPFSLT;
5839 }
5840
5841 static int compareAopfirstpass=1;
5842
5843 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5844             operand *oper, int offset, operand *result,
5845             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5846             symbol *tlbl)
5847 {
5848   int op;
5849   symbol *truelbl;
5850
5851   /* invert if there is a result to be loaded, in order to fit,
5852    * SETC/CLRC sequence */
5853   if(AOP_SIZE(result))invert_op ^= 1;
5854
5855 //  if(sign && !offset)invert_op ^= 1;
5856   
5857 //  if(sign)invert_op ^= 1;
5858   
5859   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5860
5861   if(AOP_SIZE(result) && compareAopfirstpass) {
5862     if(!ifx) {
5863       if(pcop2)
5864         pic16_emitpcode(POC_SETF, pcop2);
5865       else
5866         emitSETC;
5867     } else {
5868       if(pcop2)
5869         pic16_emitpcode(POC_CLRF, pcop2);
5870       else
5871         emitCLRC;
5872     }
5873   }
5874
5875   compareAopfirstpass = 0;
5876
5877       /* there is a bug when comparing operands with size > 1,
5878        * because higher bytes can be equal and test should be performed
5879        * to the next lower byte, current algorithm, considers operands
5880        * inequal in these cases! -- VR 20041107 */
5881
5882     
5883   if(pcop)
5884     pic16_emitpcode(op, pcop);
5885   else
5886     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5887
5888
5889   if((!sign || !offset) && AOP_SIZE(result)) {
5890     if(!ifx) {
5891       if(pcop2)
5892         pic16_emitpcode(POC_CLRF, pcop2);
5893         else
5894         emitCLRC;
5895     } else {
5896       if(pcop2)
5897         pic16_emitpcode(POC_SETF, pcop2);
5898       else
5899         emitSETC;
5900     }
5901     
5902     /* don't emit final branch (offset == 0) */
5903     if(offset) {
5904
5905       if(pcop2)
5906         pic16_emitpcode(POC_RRCF, pcop2);
5907
5908       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5909     }
5910   } else {
5911     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5912       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5913             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5914
5915       truelbl = newiTempLabel( NULL );
5916       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5917       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5918         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5919       else
5920         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5921       pic16_emitpLabel(truelbl->key);
5922     } else {
5923       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5924     }
5925   }
5926 }
5927
5928
5929   
5930
5931 #if 1   /* { */
5932 static void genCmp (operand *left, operand *right,
5933                     operand *result, iCode *ifx, int sign)
5934 {
5935   int size, cmpop=1;
5936   long lit = 0L;
5937   resolvedIfx rFalseIfx;
5938   symbol *falselbl, *tlbl;
5939
5940     FENTRY;
5941     
5942     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5943
5944     resolveIfx(&rFalseIfx, ifx);
5945     size = max(AOP_SIZE(left), AOP_SIZE(right));
5946     
5947     /* if left & right are bit variables */
5948     if(AOP_TYPE(left) == AOP_CRY
5949       && AOP_TYPE(right) == AOP_CRY ) {
5950
5951         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5953         
5954         werror(W_POSSBUG2, __FILE__, __LINE__);
5955         exit(-1);
5956     }
5957     
5958     /* if literal is on the right then swap with left */
5959     if((AOP_TYPE(right) == AOP_LIT)) {
5960       operand *tmp = right ;
5961 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5962
5963         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5964
5965 //      lit = (lit - 1) & mask;
5966         right = left;
5967         left = tmp;
5968         rFalseIfx.condition ^= 1;               /* reverse compare */
5969     } else
5970     if ((AOP_TYPE(left) == AOP_LIT)) {
5971       /* float compares are handled by support functions */
5972       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5973     }
5974
5975     /* actual comparing algorithm */
5976 //    size = AOP_SIZE( right );
5977
5978     falselbl = newiTempLabel( NULL );
5979     if(AOP_TYPE(left) == AOP_LIT) {
5980       /* compare to literal */
5981       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5982       
5983       if(sign) {
5984         pCodeOp *pct, *pct2;
5985         symbol *tlbl1;
5986
5987         /* signed compare */
5988         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5989
5990         pct = pic16_popCopyReg(&pic16_pc_prodl);
5991         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5992         tlbl = newiTempLabel( NULL );
5993         
5994         /* first compare signs:
5995          *  a. if both are positive, compare just like unsigned
5996          *  b. if both are negative, invert cmpop, compare just like unsigned
5997          *  c. if different signs, determine the result directly */
5998
5999         size--;
6000
6001 #if 1
6002         /* { */
6003         tlbl1 = newiTempLabel( NULL );
6004 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6005
6006         if(lit > 0) {
6007
6008           /* literal is zero or positive:
6009            *  a. if carry is zero, too, continue compare,
6010            *  b. if carry is set, then continue depending on cmpop ^ condition:
6011            *    1. '<' return false (literal < variable),
6012            *    2. '>' return true (literal > variable) */
6013 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6014           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6015           
6016           
6017           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6018           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6019         } else 
6020         if(lit < 0) {
6021           
6022           /* literal is negative:
6023            *  a. if carry is set, too, continue compare,
6024            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6025            *    1. '<' return true (literal < variable),
6026            *    2. '>' return false (literal > variable) */
6027 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6028           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6029           
6030           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6031           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6032         }
6033 #if 1
6034         else {
6035           /* lit == 0 */
6036           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6037           
6038           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6039           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6040         }
6041 #endif
6042         
6043         
6044         pic16_emitpLabel( tlbl1->key );
6045 #endif  /* } */
6046
6047         compareAopfirstpass=1;
6048 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6049 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6050 //        pic16_emitpcode(POC_MOVWF, pct);
6051
6052 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6053         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6054 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6055         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6056
6057         /* generic case */        
6058           while( size-- ) {
6059 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6060 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6061 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6062 //            pic16_emitpcode(POC_MOVWF, pct);
6063
6064 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6065             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6066             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6067 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6068 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6069           }
6070 //        }
6071         
6072         if(ifx)ifx->generated = 1;
6073
6074         if(AOP_SIZE(result)) {
6075           pic16_emitpLabel(tlbl->key);
6076           pic16_emitpLabel(falselbl->key);
6077           pic16_outBitOp( result, pct2 );
6078         } else {
6079           pic16_emitpLabel(tlbl->key);
6080         }
6081       } else {
6082
6083
6084         /* unsigned compare */      
6085         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6086     
6087         compareAopfirstpass=1;
6088         while(size--) {
6089           
6090           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6091           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6092
6093         }
6094
6095         if(ifx)ifx->generated = 1;
6096
6097
6098         if(AOP_SIZE(result)) {
6099           pic16_emitpLabel(falselbl->key);
6100           pic16_outBitC( result );
6101         }
6102
6103       }
6104     } else {
6105       /* compare registers */
6106       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6107
6108
6109       if(sign) {
6110         pCodeOp *pct, *pct2;
6111         
6112         /* signed compare */
6113         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6114
6115         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6116         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6117         tlbl = newiTempLabel( NULL );
6118         
6119         compareAopfirstpass=1;
6120
6121         size--;
6122         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6123 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6124         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6125         pic16_emitpcode(POC_MOVWF, pct);
6126
6127         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6128 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6129         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6130
6131         /* WREG already holds left + 0x80 */
6132         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6133         
6134         while( size-- ) {
6135           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6136 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6137           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6138           pic16_emitpcode(POC_MOVWF, pct);
6139                 
6140           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6141 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6142           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6143
6144           /* WREG already holds left + 0x80 */
6145           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6147         }
6148         
6149         if(ifx)ifx->generated = 1;
6150
6151         if(AOP_SIZE(result)) {
6152           pic16_emitpLabel(tlbl->key);
6153           pic16_emitpLabel(falselbl->key);
6154           pic16_outBitOp( result, pct2 );
6155         } else {
6156           pic16_emitpLabel(tlbl->key);
6157         }
6158
6159       } else {
6160         /* unsigned compare */      
6161         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6162
6163         compareAopfirstpass=1;
6164         while(size--) {
6165           
6166           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6167           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6168
6169         }
6170
6171         if(ifx)ifx->generated = 1;
6172         if(AOP_SIZE(result)) {
6173
6174           pic16_emitpLabel(falselbl->key);
6175           pic16_outBitC( result );
6176         }
6177
6178       }
6179     }
6180 }
6181
6182 #else    /* } else { */
6183
6184 /* new version of genCmp -- VR 20041012 */
6185 static void genCmp (operand *left,operand *right,
6186                     operand *result, iCode *ifx, int sign)
6187 {
6188   int size; //, offset = 0 ;
6189   unsigned long lit = 0L,i = 0;
6190   resolvedIfx rFalseIfx;
6191   int willCheckCarry=0;
6192   //  resolvedIfx rTrueIfx;
6193   symbol *truelbl;
6194
6195     FENTRY;
6196   
6197   /* General concept:
6198    * subtract right from left if at the end the carry flag is set then we
6199    * know that left is greater than right */
6200             
6201   resolveIfx(&rFalseIfx,ifx);
6202   truelbl  = newiTempLabel(NULL);
6203   size = max(AOP_SIZE(left),AOP_SIZE(right));
6204
6205   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6206
6207   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6208    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6209   
6210
6211   /* if literal is on the right then swap with left */
6212   if ((AOP_TYPE(right) == AOP_LIT)) {
6213     operand *tmp = right ;
6214     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6215
6216       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6217
6218 //      lit = (lit - 1) & mask;
6219       right = left;
6220       left = tmp;
6221       rFalseIfx.condition ^= 1;         /* reverse compare */
6222   } else
6223   if ((AOP_TYPE(left) == AOP_LIT)) {
6224     /* float compares are handled by support functions */
6225     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6226   }
6227
6228
6229   //if(IC_TRUE(ifx) == NULL)
6230   /* if left & right are bit variables */
6231   if (AOP_TYPE(left) == AOP_CRY &&
6232       AOP_TYPE(right) == AOP_CRY ) {
6233
6234     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6235     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6236
6237   } else {
6238     symbol *lbl  = newiTempLabel(NULL);
6239
6240     if(AOP_TYPE(left) == AOP_LIT) {
6241       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6242
6243       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6244         willCheckCarry = 1;
6245       else willCheckCarry = 0;
6246
6247       /* Special cases */
6248       if((lit == 0) && (sign == 0)) {
6249         /* unsigned compare to 0 */
6250         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6251         
6252         size--;
6253         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6254         while(size) 
6255           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6256
6257         genSkipz2(&rFalseIfx,0);
6258         if(ifx)ifx->generated = 1;
6259         return;
6260       }
6261
6262       if(size==1) {
6263         /* Special cases */
6264         lit &= 0xff;
6265         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6266           /* degenerate compare can never be true */
6267           if(rFalseIfx.condition == 0)
6268             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6269
6270           if(ifx) ifx->generated = 1;
6271           return;
6272         }
6273
6274         if(sign) {
6275           /* signed comparisons to a literal byte */
6276           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6277
6278           int lp1 = (lit+1) & 0xff;
6279
6280           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6281           switch (lp1) {
6282           case 0:
6283             rFalseIfx.condition ^= 1;
6284             genSkipCond(&rFalseIfx,right,0,7);
6285             break;
6286           case 0x7f:
6287             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6288             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6289             genSkipz2(&rFalseIfx,1);
6290             break;
6291           default:
6292             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6293             
6294             if(rFalseIfx.condition)
6295               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6296             else
6297               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6298
6299             if(willCheckCarry) {
6300               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6301               else { emitSETC; emitCLRC; }
6302               
6303             } else {
6304               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6305             }              
6306                       
6307 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6308             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6309             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6310             rFalseIfx.condition ^= 1;
6311             genSkipc(&rFalseIfx);
6312 */
6313             break;
6314           }
6315         } else {
6316           /* unsigned comparisons to a literal byte */
6317           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6318
6319           switch(lit & 0xff ) {
6320                           /* special cases */
6321           case 0:
6322             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6323             genSkipz2(&rFalseIfx,0);
6324             break;
6325           case 0x7f:
6326             rFalseIfx.condition ^= 1;
6327             genSkipCond(&rFalseIfx,right,0,7);
6328             break;
6329           default:
6330             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6331             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6332             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6333             rFalseIfx.condition ^= 1;
6334             if (AOP_TYPE(result) == AOP_CRY)
6335               genSkipc(&rFalseIfx);
6336             else {
6337               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6338               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6339             }         
6340             break;
6341           }
6342         }
6343
6344         if(ifx) ifx->generated = 1;
6345         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6346                 goto check_carry;
6347         return;
6348
6349       } else {
6350
6351         /* Size is greater than 1 */
6352
6353         if(sign) {
6354           int lp1 = lit+1;
6355
6356           size--;
6357
6358           if(lp1 == 0) {
6359             /* this means lit = 0xffffffff, or -1 */
6360
6361
6362             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6363             rFalseIfx.condition ^= 1;
6364             genSkipCond(&rFalseIfx,right,size,7);
6365             if(ifx) ifx->generated = 1;
6366             return;
6367           }
6368
6369           if(lit == 0) {
6370             int s = size;
6371
6372             if(rFalseIfx.condition) {
6373               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6374               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6375             }
6376
6377             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6378             while(size--)
6379               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6380
6381
6382             emitSKPZ;
6383             if(rFalseIfx.condition) {
6384               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6385               pic16_emitpLabel(truelbl->key);
6386             }else {
6387               rFalseIfx.condition ^= 1;
6388               genSkipCond(&rFalseIfx,right,s,7);
6389             }
6390
6391             if(ifx) ifx->generated = 1;
6392             return;
6393           }
6394
6395           if((size == 1) &&  (0 == (lp1&0xff))) {
6396             /* lower byte of signed word is zero */
6397             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6398             i = ((lp1 >> 8) & 0xff) ^0x80;
6399             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6400             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6401             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6402             rFalseIfx.condition ^= 1;
6403             genSkipc(&rFalseIfx);
6404
6405
6406             if(ifx) ifx->generated = 1;
6407             return;
6408           }
6409
6410           if(lit & (0x80 << (size*8))) {
6411             /* Lit is less than zero */
6412             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6413             //rFalseIfx.condition ^= 1;
6414             //genSkipCond(&rFalseIfx,left,size,7);
6415             //rFalseIfx.condition ^= 1;
6416             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6417             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6418
6419             if(rFalseIfx.condition)
6420               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6421             else
6422               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6423
6424
6425           } else {
6426             /* Lit is greater than or equal to zero */
6427             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6428             //rFalseIfx.condition ^= 1;
6429             //genSkipCond(&rFalseIfx,right,size,7);
6430             //rFalseIfx.condition ^= 1;
6431
6432             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6433             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6434
6435             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6436             if(rFalseIfx.condition)
6437               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6438             else
6439               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6440
6441           }
6442
6443
6444           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6445           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6446
6447           while(size--) {
6448
6449             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6450             emitSKPNZ;
6451             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6452           }
6453           rFalseIfx.condition ^= 1;
6454           //rFalseIfx.condition = 1;
6455           genSkipc(&rFalseIfx);
6456
6457           pic16_emitpLabel(truelbl->key);
6458
6459           if(ifx) ifx->generated = 1;
6460           return;
6461           // end of if (sign)
6462         } else {
6463
6464           /* compare word or long to an unsigned literal on the right.*/
6465
6466
6467           size--;
6468           if(lit < 0xff) {
6469             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6470             switch (lit) {
6471             case 0:
6472               break; /* handled above */
6473 /*
6474             case 0xff:
6475               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6476               while(size--)
6477                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6478               genSkipz2(&rFalseIfx,0);
6479               break;
6480 */
6481             default:
6482               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6483               while(--size)
6484                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6485
6486               emitSKPZ;
6487               if(rFalseIfx.condition)
6488                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6489               else
6490                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6491
6492
6493               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6494               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6495
6496               rFalseIfx.condition ^= 1;
6497               genSkipc(&rFalseIfx);
6498             }
6499
6500             pic16_emitpLabel(truelbl->key);
6501
6502             if(ifx) ifx->generated = 1;
6503             return;
6504           }
6505
6506
6507           lit++;
6508           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6509           i = (lit >> (size*8)) & 0xff;
6510
6511           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6512           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6513
6514           while(size--) {
6515             i = (lit >> (size*8)) & 0xff;
6516
6517             if(i) {
6518               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6519               emitSKPNZ;
6520               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6521             } else {
6522               /* this byte of the lit is zero, 
6523                * if it's not the last then OR in the variable */
6524               if(size)
6525                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6526             }
6527           }
6528
6529
6530           pic16_emitpLabel(lbl->key);
6531
6532           rFalseIfx.condition ^= 1;
6533
6534           genSkipc(&rFalseIfx);
6535         }
6536
6537         if(sign)
6538           pic16_emitpLabel(truelbl->key);
6539         if(ifx) ifx->generated = 1;
6540         return;
6541       }
6542     }
6543     /* Compare two variables */
6544
6545     DEBUGpic16_emitcode(";sign","%d",sign);
6546
6547     size--;
6548     if(sign) {
6549       /* Sigh. thus sucks... */
6550       if(size) {
6551         pCodeOp *pctemp;
6552         
6553         pctemp = pic16_popGetTempReg(1);
6554         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6555         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6556         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6557         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6558         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6559         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6560         pic16_popReleaseTempReg(pctemp, 1);
6561       } else {
6562         /* Signed char comparison */
6563         /* Special thanks to Nikolai Golovchenko for this snippet */
6564         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6565         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6566         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6567         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6568         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6569         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6570
6571         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6572         genSkipc(&rFalseIfx);
6573           
6574         if(ifx) ifx->generated = 1;
6575         return;
6576       }
6577
6578     } else {
6579
6580       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6581       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6582     }
6583
6584
6585     /* The rest of the bytes of a multi-byte compare */
6586     while (size) {
6587
6588       emitSKPZ;
6589       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6590       size--;
6591
6592       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6593       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6594
6595
6596     }
6597
6598     pic16_emitpLabel(lbl->key);
6599
6600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6601     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6602         (AOP_TYPE(result) == AOP_REG)) {
6603       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6604       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6605     } else {
6606       genSkipc(&rFalseIfx);
6607     }         
6608     //genSkipc(&rFalseIfx);
6609     if(ifx) ifx->generated = 1;
6610
6611     return;
6612
6613   }
6614
6615 check_carry:
6616   if ((AOP_TYPE(result) != AOP_CRY) 
6617         && AOP_SIZE(result)) {
6618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6619
6620     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6621
6622     pic16_outBitC(result);
6623   } else {
6624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6625     /* if the result is used in the next
6626        ifx conditional branch then generate
6627        code a little differently */
6628     if (ifx )
6629       genIfxJump (ifx,"c");
6630     else
6631       pic16_outBitC(result);
6632     /* leave the result in acc */
6633   }
6634
6635 }
6636 #endif  /* } */
6637
6638
6639 #endif  /* } */
6640
6641
6642
6643 /*-----------------------------------------------------------------*/
6644 /* genCmpGt :- greater than comparison                             */
6645 /*-----------------------------------------------------------------*/
6646 static void genCmpGt (iCode *ic, iCode *ifx)
6647 {
6648   operand *left, *right, *result;
6649   sym_link *letype , *retype;
6650   int sign ;
6651
6652     FENTRY;
6653     
6654     left = IC_LEFT(ic);
6655     right= IC_RIGHT(ic);
6656     result = IC_RESULT(ic);
6657
6658     letype = getSpec(operandType(left));
6659     retype =getSpec(operandType(right));
6660     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6661     /* assign the amsops */
6662     pic16_aopOp (left,ic,FALSE);
6663     pic16_aopOp (right,ic,FALSE);
6664     pic16_aopOp (result,ic,TRUE);
6665
6666     genCmp(right, left, result, ifx, sign);
6667
6668     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6669     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6670     pic16_freeAsmop(result,NULL,ic,TRUE); 
6671 }
6672
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpLt - less than comparisons                                */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpLt (iCode *ic, iCode *ifx)
6677 {
6678   operand *left, *right, *result;
6679   sym_link *letype , *retype;
6680   int sign ;
6681
6682     FENTRY;
6683
6684     left = IC_LEFT(ic);
6685     right= IC_RIGHT(ic);
6686     result = IC_RESULT(ic);
6687
6688     letype = getSpec(operandType(left));
6689     retype =getSpec(operandType(right));
6690     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6691
6692     /* assign the amsops */
6693     pic16_aopOp (left,ic,FALSE);
6694     pic16_aopOp (right,ic,FALSE);
6695     pic16_aopOp (result,ic,TRUE);
6696
6697     genCmp(left, right, result, ifx, sign);
6698
6699     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6700     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6701     pic16_freeAsmop(result,NULL,ic,TRUE); 
6702 }
6703
6704 #if 0
6705 // not needed ATM
6706 // FIXME reenable literal optimisation when the pic16 port is stable
6707
6708 /*-----------------------------------------------------------------*/
6709 /* genc16bit2lit - compare a 16 bit value to a literal             */
6710 /*-----------------------------------------------------------------*/
6711 static void genc16bit2lit(operand *op, int lit, int offset)
6712 {
6713   int i;
6714
6715   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6716   if( (lit&0xff) == 0) 
6717     i=1;
6718   else
6719     i=0;
6720
6721   switch( BYTEofLONG(lit,i)) { 
6722   case 0:
6723     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6724     break;
6725   case 1:
6726     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6727     break;
6728   case 0xff:
6729     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6730     break;
6731   default:
6732     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6733     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6734   }
6735
6736   i ^= 1;
6737
6738   switch( BYTEofLONG(lit,i)) { 
6739   case 0:
6740     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6741     break;
6742   case 1:
6743     emitSKPNZ;
6744     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6745     break;
6746   case 0xff:
6747     emitSKPNZ;
6748     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6749     break;
6750   default:
6751     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6752     emitSKPNZ;
6753     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6754
6755   }
6756
6757 }
6758 #endif
6759
6760 #if 0
6761 // not needed ATM
6762 /*-----------------------------------------------------------------*/
6763 /* gencjneshort - compare and jump if not equal                    */
6764 /*-----------------------------------------------------------------*/
6765 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6766 {
6767   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6768   int offset = 0;
6769   int res_offset = 0;  /* the result may be a different size then left or right */
6770   int res_size = AOP_SIZE(result);
6771   resolvedIfx rIfx;
6772   symbol *lbl, *lbl_done;
6773
6774   unsigned long lit = 0L;
6775   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6776
6777   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6778   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6779   if(result)
6780     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6781   resolveIfx(&rIfx,ifx);
6782   lbl =  newiTempLabel(NULL);
6783   lbl_done =  newiTempLabel(NULL);
6784
6785
6786   /* if the left side is a literal or 
6787      if the right is in a pointer register and left 
6788      is not */
6789   if ((AOP_TYPE(left) == AOP_LIT) || 
6790       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6791     operand *t = right;
6792     right = left;
6793     left = t;
6794   }
6795   if(AOP_TYPE(right) == AOP_LIT)
6796     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6797
6798   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6799     preserve_result = 1;
6800
6801   if(result && !preserve_result)
6802     {
6803       int i;
6804       for(i = 0; i < AOP_SIZE(result); i++)
6805         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6806     }
6807
6808
6809   /* if the right side is a literal then anything goes */
6810   if (AOP_TYPE(right) == AOP_LIT &&
6811       AOP_TYPE(left) != AOP_DIR ) {
6812     switch(size) {
6813     case 2:
6814       genc16bit2lit(left, lit, 0);
6815       emitSKPZ;
6816       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6817       break;
6818     default:
6819       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6820       while (size--) {
6821         if(lit & 0xff) {
6822           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6823           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6824         } else {
6825           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6826         }
6827
6828         emitSKPZ;
6829         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6830         offset++;
6831         if(res_offset < res_size-1)
6832           res_offset++;
6833         lit >>= 8;
6834       }
6835       break;
6836     }
6837   }
6838
6839   /* if the right side is in a register or in direct space or
6840      if the left is a pointer register & right is not */    
6841   else if (AOP_TYPE(right) == AOP_REG ||
6842            AOP_TYPE(right) == AOP_DIR || 
6843            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6844            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6845     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6846     int lbl_key = lbl->key;
6847
6848     if(result) {
6849       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6850       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6851     }else {
6852       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6853       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6854               __FUNCTION__,__LINE__);
6855       return;
6856     }
6857    
6858 /*     switch(size) { */
6859 /*     case 2: */
6860 /*       genc16bit2lit(left, lit, 0); */
6861 /*       emitSKPNZ; */
6862 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6863 /*       break; */
6864 /*     default: */
6865     while (size--) {
6866       int emit_skip=1;
6867       if((AOP_TYPE(left) == AOP_DIR) && 
6868          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6869
6870         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6871         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6872
6873       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6874             
6875         switch (lit & 0xff) {
6876         case 0:
6877           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6878           break;
6879         case 1:
6880           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6881           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6882           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6883           emit_skip=0;
6884           break;
6885         case 0xff:
6886           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6887           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6888           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6889           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6890           emit_skip=0;
6891           break;
6892         default:
6893           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6894           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6895         }
6896         lit >>= 8;
6897
6898       } else {
6899         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6900       }
6901       if(emit_skip) {
6902         if(AOP_TYPE(result) == AOP_CRY) {
6903           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6904           if(rIfx.condition)
6905             emitSKPNZ;
6906           else
6907             emitSKPZ;
6908           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6909         } else {
6910           /* fix me. probably need to check result size too */
6911           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6912           if(rIfx.condition)
6913             emitSKPZ;
6914           else
6915             emitSKPNZ;
6916           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6917           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6918         }
6919         if(ifx)
6920           ifx->generated=1;
6921       }
6922       emit_skip++;
6923       offset++;
6924       if(res_offset < res_size-1)
6925         res_offset++;
6926     }
6927 /*       break; */
6928 /*     } */
6929   } else if(AOP_TYPE(right) == AOP_REG &&
6930             AOP_TYPE(left) != AOP_DIR){
6931
6932     while(size--) {
6933       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6934       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6935       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6936       if(rIfx.condition)
6937         emitSKPNZ;
6938       else
6939         emitSKPZ;
6940       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6941       offset++;
6942       if(res_offset < res_size-1)
6943         res_offset++;
6944     }
6945       
6946   }else{
6947     /* right is a pointer reg need both a & b */
6948     while(size--) {
6949       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6950       if(strcmp(l,"b"))
6951         pic16_emitcode("mov","b,%s",l);
6952       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6953       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6954       offset++;
6955     }
6956   }
6957
6958   if(result && preserve_result)
6959     {
6960       int i;
6961       for(i = 0; i < AOP_SIZE(result); i++)
6962         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6963     }
6964
6965   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6966
6967   if(result && preserve_result)
6968     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6969
6970   if(!rIfx.condition)
6971     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6972
6973   pic16_emitpLabel(lbl->key);
6974
6975   if(result && preserve_result)
6976     {
6977       int i;
6978       for(i = 0; i < AOP_SIZE(result); i++)
6979         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6980
6981       pic16_emitpLabel(lbl_done->key);
6982    }
6983
6984   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6985
6986   if(ifx)
6987     ifx->generated = 1;
6988 }
6989 #endif
6990
6991 #if 0
6992 /*-----------------------------------------------------------------*/
6993 /* gencjne - compare and jump if not equal                         */
6994 /*-----------------------------------------------------------------*/
6995 static void gencjne(operand *left, operand *right, iCode *ifx)
6996 {
6997     symbol *tlbl  = newiTempLabel(NULL);
6998
6999     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7000     gencjneshort(left, right, lbl);
7001
7002     pic16_emitcode("mov","a,%s",one);
7003     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7004     pic16_emitcode("","%05d_DS_:",lbl->key+100);
7005     pic16_emitcode("clr","a");
7006     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7007
7008     pic16_emitpLabel(lbl->key);
7009     pic16_emitpLabel(tlbl->key);
7010
7011 }
7012 #endif
7013
7014
7015 /*-----------------------------------------------------------------*/
7016 /* is_LitOp - check if operand has to be treated as literal        */
7017 /*-----------------------------------------------------------------*/
7018 static bool is_LitOp(operand *op)
7019 {
7020   return ((AOP_TYPE(op) == AOP_LIT)
7021       || ( (AOP_TYPE(op) == AOP_PCODE)
7022           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7023               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7024 }
7025
7026 /*-----------------------------------------------------------------*/
7027 /* is_LitAOp - check if operand has to be treated as literal        */
7028 /*-----------------------------------------------------------------*/
7029 static bool is_LitAOp(asmop *aop)
7030 {
7031   return ((aop->type == AOP_LIT)
7032       || ( (aop->type == AOP_PCODE)
7033           && ( (aop->aopu.pcop->type == PO_LITERAL)
7034               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7035 }
7036
7037
7038
7039 /*-----------------------------------------------------------------*/
7040 /* genCmpEq - generates code for equal to                          */
7041 /*-----------------------------------------------------------------*/
7042 static void genCmpEq (iCode *ic, iCode *ifx)
7043 {
7044   operand *left, *right, *result;
7045   symbol *falselbl = newiTempLabel(NULL);
7046   symbol *donelbl = newiTempLabel(NULL);
7047
7048   int preserve_result = 0;
7049   int generate_result = 0;
7050   int i=0;
7051
7052   FENTRY;
7053   
7054   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7055   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7056   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7057  
7058   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7059
7060   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7061     {
7062       werror(W_POSSBUG2, __FILE__, __LINE__);
7063       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
7064       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7065       goto release;
7066     }
7067
7068   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7069     {
7070       operand *tmp = right ;
7071       right = left;
7072       left = tmp;
7073     }
7074
7075   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7076     preserve_result = 1;
7077
7078   if(result && AOP_SIZE(result))
7079     generate_result = 1;
7080
7081   if(generate_result && !preserve_result)
7082     {
7083       for(i = 0; i < AOP_SIZE(result); i++)
7084         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7085     }
7086
7087   for(i=0; i < AOP_SIZE(left); i++)
7088     {
7089       if(AOP_TYPE(left) != AOP_ACC)
7090         {
7091           if(is_LitOp(left))
7092             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7093           else
7094             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7095         }
7096       if(is_LitOp(right))
7097         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7098       else
7099         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7100
7101       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7102     }
7103
7104   // result == true
7105
7106   if(generate_result && preserve_result)
7107     {
7108       for(i = 0; i < AOP_SIZE(result); i++)
7109         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7110     }
7111
7112   if(generate_result)
7113     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7114
7115   if(generate_result && preserve_result)
7116     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7117
7118   if(ifx && IC_TRUE(ifx))
7119     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7120
7121   if(ifx && IC_FALSE(ifx))
7122     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7123
7124   pic16_emitpLabel(falselbl->key);
7125
7126   // result == false
7127
7128   if(ifx && IC_FALSE(ifx))
7129     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7130
7131   if(generate_result && preserve_result)
7132     {
7133       for(i = 0; i < AOP_SIZE(result); i++)
7134         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7135     }
7136
7137   pic16_emitpLabel(donelbl->key);
7138
7139   if(ifx)
7140     ifx->generated = 1;
7141
7142 release:
7143   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7144   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7145   pic16_freeAsmop(result,NULL,ic,TRUE);
7146
7147 }
7148
7149
7150 #if 0
7151 // old version kept for reference
7152
7153 /*-----------------------------------------------------------------*/
7154 /* genCmpEq - generates code for equal to                          */
7155 /*-----------------------------------------------------------------*/
7156 static void genCmpEq (iCode *ic, iCode *ifx)
7157 {
7158     operand *left, *right, *result;
7159     unsigned long lit = 0L;
7160     int size,offset=0;
7161     symbol *falselbl  = newiTempLabel(NULL);
7162
7163
7164     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7165
7166     if(ifx)
7167       DEBUGpic16_emitcode ("; ifx is non-null","");
7168     else
7169       DEBUGpic16_emitcode ("; ifx is null","");
7170
7171     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7172     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7173     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7174
7175     size = max(AOP_SIZE(left),AOP_SIZE(right));
7176
7177     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7178
7179     /* if literal, literal on the right or 
7180     if the right is in a pointer register and left 
7181     is not */
7182     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7183         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7184       operand *tmp = right ;
7185       right = left;
7186       left = tmp;
7187     }
7188
7189
7190     if(ifx && !AOP_SIZE(result)){
7191         symbol *tlbl;
7192         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7193         /* if they are both bit variables */
7194         if (AOP_TYPE(left) == AOP_CRY &&
7195             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7196                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7197             if(AOP_TYPE(right) == AOP_LIT){
7198                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7199                 if(lit == 0L){
7200                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7201                     pic16_emitcode("cpl","c");
7202                 } else if(lit == 1L) {
7203                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7204                 } else {
7205                     pic16_emitcode("clr","c");
7206                 }
7207                 /* AOP_TYPE(right) == AOP_CRY */
7208             } else {
7209                 symbol *lbl = newiTempLabel(NULL);
7210                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7211                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7212                 pic16_emitcode("cpl","c");
7213                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7214             }
7215             /* if true label then we jump if condition
7216             supplied is true */
7217             tlbl = newiTempLabel(NULL);
7218             if ( IC_TRUE(ifx) ) {
7219                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7220                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7221             } else {
7222                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7223                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7224             }
7225             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7226
7227                 {
7228                 /* left and right are both bit variables, result is carry */
7229                         resolvedIfx rIfx;
7230               
7231                         resolveIfx(&rIfx,ifx);
7232
7233                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7234                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7235                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7236                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7237                         genSkipz2(&rIfx,0);
7238                 }
7239         } else {
7240
7241                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7242
7243                         /* They're not both bit variables. Is the right a literal? */
7244                         if(AOP_TYPE(right) == AOP_LIT) {
7245                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7246             
7247                         switch(size) {
7248
7249                                 case 1:
7250                                         switch(lit & 0xff) {
7251                                                 case 1:
7252                                                                 if ( IC_TRUE(ifx) ) {
7253                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7254                                                                         emitSKPNZ;
7255                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7256                                                                 } else {
7257                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7258                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7259                                                                 }
7260                                                                 break;
7261                                                 case 0xff:
7262                                                                 if ( IC_TRUE(ifx) ) {
7263                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7264                                                                         emitSKPNZ;
7265                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7266                                                                 } else {
7267                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7268                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7269                                                                 }
7270                                                                 break;
7271                                                 default:
7272                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7273                                                                 if(lit)
7274                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7275                                                                 genSkip(ifx,'z');
7276                                         } // switch lit
7277
7278
7279                                         /* end of size == 1 */
7280                                         break;
7281               
7282                                 case 2:
7283                                         genc16bit2lit(left,lit,offset);
7284                                         genSkip(ifx,'z');
7285                                         break;
7286                                         /* end of size == 2 */
7287
7288                                 default:
7289                                         /* size is 4 */
7290                                         if(lit==0) {
7291                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7292                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7293                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7294                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7295                                                 genSkip(ifx,'z');
7296                                         } else {
7297                                                 /* search for patterns that can be optimized */
7298
7299                                                 genc16bit2lit(left,lit,0);
7300                                                 lit >>= 16;
7301                                                 if(lit) {
7302                                                                 if(IC_TRUE(ifx))
7303                                                                 emitSKPZ; // if hi word unequal
7304                                                                 else
7305                                                                 emitSKPNZ; // if hi word equal
7306                                                                 // fail early
7307                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7308                                                         genc16bit2lit(left,lit,2);
7309                                                         genSkip(ifx,'z');
7310                                                 } else {
7311                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7312                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7313                                                         genSkip(ifx,'z');
7314                                                 }
7315                                         }
7316                                                 pic16_emitpLabel(falselbl->key);
7317                                                 break;
7318
7319                         } // switch size
7320           
7321                         ifx->generated = 1;
7322                         goto release ;
7323             
7324
7325           } else if(AOP_TYPE(right) == AOP_CRY ) {
7326             /* we know the left is not a bit, but that the right is */
7327             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7328             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7329                       pic16_popGet(AOP(right),offset));
7330             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7331
7332             /* if the two are equal, then W will be 0 and the Z bit is set
7333              * we could test Z now, or go ahead and check the high order bytes if
7334              * the variable we're comparing is larger than a byte. */
7335
7336             while(--size)
7337               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7338
7339             if ( IC_TRUE(ifx) ) {
7340               emitSKPNZ;
7341               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7342               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7343             } else {
7344               emitSKPZ;
7345               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7346               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7347             }
7348
7349           } else {
7350             /* They're both variables that are larger than bits */
7351             int s = size;
7352
7353             tlbl = newiTempLabel(NULL);
7354
7355             while(size--) {
7356               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7357               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7358
7359               if ( IC_TRUE(ifx) ) {
7360                 if(size) {
7361                   emitSKPZ;
7362                 
7363                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7364
7365                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7366                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7367                 } else {
7368                   emitSKPNZ;
7369
7370                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7371
7372
7373                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7374                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7375                 }
7376               } else {
7377                 emitSKPZ;
7378
7379                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7380
7381                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7382                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7383               }
7384               offset++;
7385             }
7386             if(s>1 && IC_TRUE(ifx)) {
7387               pic16_emitpLabel(tlbl->key);
7388               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7389             }
7390           }
7391         }
7392         /* mark the icode as generated */
7393         ifx->generated = 1;
7394         goto release ;
7395     }
7396
7397     /* if they are both bit variables */
7398     if (AOP_TYPE(left) == AOP_CRY &&
7399         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7400         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7401         if(AOP_TYPE(right) == AOP_LIT){
7402             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7403             if(lit == 0L){
7404                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7405                 pic16_emitcode("cpl","c");
7406             } else if(lit == 1L) {
7407                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7408             } else {
7409                 pic16_emitcode("clr","c");
7410             }
7411             /* AOP_TYPE(right) == AOP_CRY */
7412         } else {
7413             symbol *lbl = newiTempLabel(NULL);
7414             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7415             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7416             pic16_emitcode("cpl","c");
7417             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7418         }
7419         /* c = 1 if egal */
7420         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7421             pic16_outBitC(result);
7422             goto release ;
7423         }
7424         if (ifx) {
7425             genIfxJump (ifx,"c");
7426             goto release ;
7427         }
7428         /* if the result is used in an arithmetic operation
7429         then put the result in place */
7430         pic16_outBitC(result);
7431     } else {
7432       
7433       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7434       gencjne(left,right,result,ifx);
7435 /*
7436       if(ifx) 
7437         gencjne(left,right,newiTempLabel(NULL));
7438       else {
7439         if(IC_TRUE(ifx)->key)
7440           gencjne(left,right,IC_TRUE(ifx)->key);
7441         else
7442           gencjne(left,right,IC_FALSE(ifx)->key);
7443         ifx->generated = 1;
7444         goto release ;
7445       }
7446       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7447         pic16_aopPut(AOP(result),"a",0);
7448         goto release ;
7449       }
7450
7451       if (ifx) {
7452         genIfxJump (ifx,"a");
7453         goto release ;
7454       }
7455 */
7456       /* if the result is used in an arithmetic operation
7457          then put the result in place */
7458 /*
7459       if (AOP_TYPE(result) != AOP_CRY) 
7460         pic16_outAcc(result);
7461 */
7462       /* leave the result in acc */
7463     }
7464
7465 release:
7466     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7467     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7468     pic16_freeAsmop(result,NULL,ic,TRUE);
7469 }
7470 #endif
7471
7472 /*-----------------------------------------------------------------*/
7473 /* ifxForOp - returns the icode containing the ifx for operand     */
7474 /*-----------------------------------------------------------------*/
7475 static iCode *ifxForOp ( operand *op, iCode *ic )
7476 {
7477   FENTRY2;
7478
7479     /* if true symbol then needs to be assigned */
7480     if (IS_TRUE_SYMOP(op))
7481         return NULL ;
7482
7483     /* if this has register type condition and
7484     the next instruction is ifx with the same operand
7485     and live to of the operand is upto the ifx only then */
7486     if (ic->next
7487         && ic->next->op == IFX
7488         && IC_COND(ic->next)->key == op->key
7489         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7490         ) {
7491                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7492           return ic->next;
7493     }
7494
7495     /*
7496     if (ic->next &&
7497         ic->next->op == IFX &&
7498         IC_COND(ic->next)->key == op->key) {
7499       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7500       return ic->next;
7501     }
7502     */
7503
7504     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7505     if (ic->next &&
7506         ic->next->op == IFX)
7507       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7508
7509     if (ic->next &&
7510         ic->next->op == IFX &&
7511         IC_COND(ic->next)->key == op->key) {
7512       DEBUGpic16_emitcode ("; "," key is okay");
7513       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7514                            OP_SYMBOL(op)->liveTo,
7515                            ic->next->seq);
7516     }
7517
7518 #if 0
7519     /* the code below is completely untested
7520      * it just allows ulong2fs.c compile -- VR */
7521          
7522     ic = ic->next;
7523     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7524                                         __FILE__, __FUNCTION__, __LINE__);
7525         
7526     /* if this has register type condition and
7527     the next instruction is ifx with the same operand
7528     and live to of the operand is upto the ifx only then */
7529     if (ic->next &&
7530         ic->next->op == IFX &&
7531         IC_COND(ic->next)->key == op->key &&
7532         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7533         return ic->next;
7534
7535     if (ic->next &&
7536         ic->next->op == IFX &&
7537         IC_COND(ic->next)->key == op->key) {
7538       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7539       return ic->next;
7540     }
7541
7542     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7543                                         __FILE__, __FUNCTION__, __LINE__);
7544
7545 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7546 #endif
7547
7548     return NULL;
7549 }
7550 /*-----------------------------------------------------------------*/
7551 /* genAndOp - for && operation                                     */
7552 /*-----------------------------------------------------------------*/
7553 static void genAndOp (iCode *ic)
7554 {
7555   operand *left,*right, *result;
7556 /*     symbol *tlbl; */
7557
7558     FENTRY;
7559
7560     /* note here that && operations that are in an
7561     if statement are taken away by backPatchLabels
7562     only those used in arthmetic operations remain */
7563     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7564     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7565     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7566
7567     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7568
7569     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7570     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7571     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7572
7573     /* if both are bit variables */
7574 /*     if (AOP_TYPE(left) == AOP_CRY && */
7575 /*         AOP_TYPE(right) == AOP_CRY ) { */
7576 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7577 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7578 /*         pic16_outBitC(result); */
7579 /*     } else { */
7580 /*         tlbl = newiTempLabel(NULL); */
7581 /*         pic16_toBoolean(left);     */
7582 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7583 /*         pic16_toBoolean(right); */
7584 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7585 /*         pic16_outBitAcc(result); */
7586 /*     } */
7587
7588     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7589     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7590     pic16_freeAsmop(result,NULL,ic,TRUE);
7591 }
7592
7593
7594 /*-----------------------------------------------------------------*/
7595 /* genOrOp - for || operation                                      */
7596 /*-----------------------------------------------------------------*/
7597 /*
7598   tsd pic port -
7599   modified this code, but it doesn't appear to ever get called
7600 */
7601
7602 static void genOrOp (iCode *ic)
7603 {
7604   operand *left,*right, *result;
7605   symbol *tlbl;
7606
7607     FENTRY;  
7608
7609   /* note here that || operations that are in an
7610     if statement are taken away by backPatchLabels
7611     only those used in arthmetic operations remain */
7612     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7613     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7614     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7615
7616     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7617
7618     /* if both are bit variables */
7619     if (AOP_TYPE(left) == AOP_CRY &&
7620         AOP_TYPE(right) == AOP_CRY ) {
7621       pic16_emitcode("clrc","");
7622       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7623                AOP(left)->aopu.aop_dir,
7624                AOP(left)->aopu.aop_dir);
7625       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7626                AOP(right)->aopu.aop_dir,
7627                AOP(right)->aopu.aop_dir);
7628       pic16_emitcode("setc","");
7629
7630     } else {
7631         tlbl = newiTempLabel(NULL);
7632         pic16_toBoolean(left);
7633         emitSKPZ;
7634         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7635         pic16_toBoolean(right);
7636         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7637
7638         pic16_outBitAcc(result);
7639     }
7640
7641     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7642     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7643     pic16_freeAsmop(result,NULL,ic,TRUE);            
7644 }
7645
7646 /*-----------------------------------------------------------------*/
7647 /* isLiteralBit - test if lit == 2^n                               */
7648 /*-----------------------------------------------------------------*/
7649 static int isLiteralBit(unsigned long lit)
7650 {
7651     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7652     0x100L,0x200L,0x400L,0x800L,
7653     0x1000L,0x2000L,0x4000L,0x8000L,
7654     0x10000L,0x20000L,0x40000L,0x80000L,
7655     0x100000L,0x200000L,0x400000L,0x800000L,
7656     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7657     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7658     int idx;
7659     
7660     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7661     for(idx = 0; idx < 32; idx++)
7662         if(lit == pw[idx])
7663             return idx+1;
7664     return 0;
7665 }
7666
7667 /*-----------------------------------------------------------------*/
7668 /* continueIfTrue -                                                */
7669 /*-----------------------------------------------------------------*/
7670 static void continueIfTrue (iCode *ic)
7671 {
7672   FENTRY;
7673   if(IC_TRUE(ic))
7674     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7675   ic->generated = 1;
7676 }
7677
7678 /*-----------------------------------------------------------------*/
7679 /* jmpIfTrue -                                                     */
7680 /*-----------------------------------------------------------------*/
7681 static void jumpIfTrue (iCode *ic)
7682 {
7683   FENTRY;
7684   if(!IC_TRUE(ic))
7685     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7686   ic->generated = 1;
7687 }
7688
7689 /*-----------------------------------------------------------------*/
7690 /* jmpTrueOrFalse -                                                */
7691 /*-----------------------------------------------------------------*/
7692 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7693 {
7694   // ugly but optimized by peephole
7695   FENTRY;
7696   if(IC_TRUE(ic)){
7697     symbol *nlbl = newiTempLabel(NULL);
7698       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7699       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7700       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7701       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7702   } else {
7703     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7704     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7705   }
7706   ic->generated = 1;
7707 }
7708
7709 /*-----------------------------------------------------------------*/
7710 /* genAnd  - code for and                                          */
7711 /*-----------------------------------------------------------------*/
7712 static void genAnd (iCode *ic, iCode *ifx)
7713 {
7714   operand *left, *right, *result;
7715   int size, offset=0;  
7716   unsigned long lit = 0L;
7717   int bytelit = 0;
7718   resolvedIfx rIfx;
7719
7720     FENTRY;
7721     
7722   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7723   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7724   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7725
7726   resolveIfx(&rIfx,ifx);
7727
7728   /* if left is a literal & right is not then exchange them */
7729   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7730       AOP_NEEDSACC(left)) {
7731     operand *tmp = right ;
7732     right = left;
7733     left = tmp;
7734   }
7735
7736   /* if result = right then exchange them */
7737   if(pic16_sameRegs(AOP(result),AOP(right))){
7738     operand *tmp = right ;
7739     right = left;
7740     left = tmp;
7741   }
7742
7743   /* if right is bit then exchange them */
7744   if (AOP_TYPE(right) == AOP_CRY &&
7745       AOP_TYPE(left) != AOP_CRY){
7746     operand *tmp = right ;
7747     right = left;
7748     left = tmp;
7749   }
7750   if(AOP_TYPE(right) == AOP_LIT)
7751     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7752
7753   size = AOP_SIZE(result);
7754
7755   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7756
7757   // if(bit & yy)
7758   // result = bit & yy;
7759   if (AOP_TYPE(left) == AOP_CRY){
7760     // c = bit & literal;
7761     if(AOP_TYPE(right) == AOP_LIT){
7762       if(lit & 1) {
7763         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7764           // no change
7765           goto release;
7766         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7767       } else {
7768         // bit(result) = 0;
7769         if(size && (AOP_TYPE(result) == AOP_CRY)){
7770           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7771           goto release;
7772         }
7773         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7774           jumpIfTrue(ifx);
7775           goto release;
7776         }
7777         pic16_emitcode("clr","c");
7778       }
7779     } else {
7780       if (AOP_TYPE(right) == AOP_CRY){
7781         // c = bit & bit;
7782         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7783         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7784       } else {
7785         // c = bit & val;
7786         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7787         // c = lsb
7788         pic16_emitcode("rrc","a");
7789         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7790       }
7791     }
7792     // bit = c
7793     // val = c
7794     if(size)
7795       pic16_outBitC(result);
7796     // if(bit & ...)
7797     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7798       genIfxJump(ifx, "c");           
7799     goto release ;
7800   }
7801
7802   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7803   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7804   if((AOP_TYPE(right) == AOP_LIT) &&
7805      (AOP_TYPE(result) == AOP_CRY) &&
7806      (AOP_TYPE(left) != AOP_CRY)){
7807     int posbit = isLiteralBit(lit);
7808     /* left &  2^n */
7809     if(posbit){
7810       posbit--;
7811       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7812       // bit = left & 2^n
7813       if(size)
7814         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7815       // if(left &  2^n)
7816       else{
7817         if(ifx){
7818 /*
7819           if(IC_TRUE(ifx)) {
7820             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7821             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7822           } else {
7823             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7824             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7825           }
7826 */
7827         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7828         size = AOP_SIZE(left);
7829
7830         {
7831           int bp = posbit, ofs=0;
7832           
7833             while(bp > 7) {
7834               bp -= 8;
7835               ofs++;
7836             }
7837         
7838           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7839                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7840
7841         }
7842 /*
7843           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7844                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7845 */
7846           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7847           
7848           ifx->generated = 1;
7849         }
7850         goto release;
7851       }
7852     } else {
7853       symbol *tlbl = newiTempLabel(NULL);
7854       int sizel = AOP_SIZE(left);
7855
7856       if(size)
7857         emitSETC;
7858
7859       while(sizel--) {
7860         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7861
7862           /* patch provided by Aaron Colwell */
7863           if((posbit = isLiteralBit(bytelit)) != 0) {
7864               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7865                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7866                                                 (posbit-1),0, PO_GPR_REGISTER));
7867
7868               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7869 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7870           } else {
7871               if (bytelit == 0xff) {
7872                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7873                    * a peephole could optimize it out -- VR */
7874                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7875               } else {
7876                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7877                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7878               }
7879
7880               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7881                             pic16_popGetLabel(tlbl->key));
7882           }
7883         
7884 #if 0
7885           /* old code, left here for reference -- VR 09/2004 */
7886           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7887           // byte ==  2^n ?
7888           if((posbit = isLiteralBit(bytelit)) != 0)
7889             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7890           else{
7891             if(bytelit != 0x0FFL)
7892               pic16_emitcode("anl","a,%s",
7893                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7894             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7895           }
7896 #endif
7897         }
7898         offset++;
7899       }
7900       // bit = left & literal
7901       if(size) {
7902         emitCLRC;
7903         pic16_emitpLabel(tlbl->key);
7904       }
7905       // if(left & literal)
7906       else {
7907         if(ifx) {
7908           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7909           ifx->generated = 1;
7910         }
7911         pic16_emitpLabel(tlbl->key);
7912         goto release;
7913       }
7914     }
7915
7916     pic16_outBitC(result);
7917     goto release ;
7918   }
7919
7920   /* if left is same as result */
7921   if(pic16_sameRegs(AOP(result),AOP(left))){
7922     int know_W = -1;
7923     for(;size--; offset++,lit>>=8) {
7924       if(AOP_TYPE(right) == AOP_LIT){
7925         switch(lit & 0xff) {
7926         case 0x00:
7927           /*  and'ing with 0 has clears the result */
7928 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7929           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7930           break;
7931         case 0xff:
7932           /* and'ing with 0xff is a nop when the result and left are the same */
7933           break;
7934
7935         default:
7936           {
7937             int p = pic16_my_powof2( (~lit) & 0xff );
7938             if(p>=0) {
7939               /* only one bit is set in the literal, so use a bcf instruction */
7940 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7941               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7942
7943             } else {
7944               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7945               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7946               if(know_W != (lit&0xff))
7947                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7948               know_W = lit &0xff;
7949               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7950             }
7951           }    
7952         }
7953       } else {
7954         if (AOP_TYPE(left) == AOP_ACC) {
7955           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7956         } else {                    
7957           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7958           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7959
7960         }
7961       }
7962     }
7963
7964   } else {
7965     // left & result in different registers
7966     if(AOP_TYPE(result) == AOP_CRY){
7967       // result = bit
7968       // if(size), result in bit
7969       // if(!size && ifx), conditional oper: if(left & right)
7970       symbol *tlbl = newiTempLabel(NULL);
7971       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7972       if(size)
7973         pic16_emitcode("setb","c");
7974       while(sizer--){
7975         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7976         pic16_emitcode("anl","a,%s",
7977                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7978         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7979         offset++;
7980       }
7981       if(size){
7982         CLRC;
7983         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7984         pic16_outBitC(result);
7985       } else if(ifx)
7986         jmpTrueOrFalse(ifx, tlbl);
7987     } else {
7988       for(;(size--);offset++) {
7989         // normal case
7990         // result = left & right
7991         if(AOP_TYPE(right) == AOP_LIT){
7992           int t = (lit >> (offset*8)) & 0x0FFL;
7993           switch(t) { 
7994           case 0x00:
7995             pic16_emitcode("clrf","%s",
7996                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7997             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7998             break;
7999           case 0xff:
8000             pic16_emitcode("movf","%s,w",
8001                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8002             pic16_emitcode("movwf","%s",
8003                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8004             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8005             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8006             break;
8007           default:
8008             pic16_emitcode("movlw","0x%x",t);
8009             pic16_emitcode("andwf","%s,w",
8010                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8011             pic16_emitcode("movwf","%s",
8012                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8013               
8014             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8015             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8016             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8017           }
8018           continue;
8019         }
8020
8021         if (AOP_TYPE(left) == AOP_ACC) {
8022           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8023           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8024         } else {
8025           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8026           pic16_emitcode("andwf","%s,w",
8027                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8028           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8029           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8030         }
8031         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8032         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8033       }
8034     }
8035   }
8036
8037   release :
8038     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8039   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8040   pic16_freeAsmop(result,NULL,ic,TRUE);     
8041 }
8042
8043 /*-----------------------------------------------------------------*/
8044 /* genOr  - code for or                                            */
8045 /*-----------------------------------------------------------------*/
8046 static void genOr (iCode *ic, iCode *ifx)
8047 {
8048     operand *left, *right, *result;
8049     int size, offset=0;
8050     unsigned long lit = 0L;
8051
8052     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8053
8054     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8055     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8056     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8057
8058     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8059
8060     /* if left is a literal & right is not then exchange them */
8061     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8062         AOP_NEEDSACC(left)) {
8063         operand *tmp = right ;
8064         right = left;
8065         left = tmp;
8066     }
8067
8068     /* if result = right then exchange them */
8069     if(pic16_sameRegs(AOP(result),AOP(right))){
8070         operand *tmp = right ;
8071         right = left;
8072         left = tmp;
8073     }
8074
8075     /* if right is bit then exchange them */
8076     if (AOP_TYPE(right) == AOP_CRY &&
8077         AOP_TYPE(left) != AOP_CRY){
8078         operand *tmp = right ;
8079         right = left;
8080         left = tmp;
8081     }
8082
8083     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8084
8085     if(AOP_TYPE(right) == AOP_LIT)
8086         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8087
8088     size = AOP_SIZE(result);
8089
8090     // if(bit | yy)
8091     // xx = bit | yy;
8092     if (AOP_TYPE(left) == AOP_CRY){
8093         if(AOP_TYPE(right) == AOP_LIT){
8094             // c = bit & literal;
8095             if(lit){
8096                 // lit != 0 => result = 1
8097                 if(AOP_TYPE(result) == AOP_CRY){
8098                   if(size)
8099                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8100                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8101                   //     AOP(result)->aopu.aop_dir,
8102                   //     AOP(result)->aopu.aop_dir);
8103                     else if(ifx)
8104                         continueIfTrue(ifx);
8105                     goto release;
8106                 }
8107             } else {
8108                 // lit == 0 => result = left
8109                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8110                     goto release;
8111                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8112             }
8113         } else {
8114             if (AOP_TYPE(right) == AOP_CRY){
8115               if(pic16_sameRegs(AOP(result),AOP(left))){
8116                 // c = bit | bit;
8117                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8118                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8119                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8120
8121                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8122                          AOP(result)->aopu.aop_dir,
8123                          AOP(result)->aopu.aop_dir);
8124                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8125                          AOP(right)->aopu.aop_dir,
8126                          AOP(right)->aopu.aop_dir);
8127                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8128                          AOP(result)->aopu.aop_dir,
8129                          AOP(result)->aopu.aop_dir);
8130               } else {
8131                 if( AOP_TYPE(result) == AOP_ACC) {
8132                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8133                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8134                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8135                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8136
8137                 } else {
8138
8139                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8140                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8141                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8142                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8143
8144                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8145                                  AOP(result)->aopu.aop_dir,
8146                                  AOP(result)->aopu.aop_dir);
8147                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8148                                  AOP(right)->aopu.aop_dir,
8149                                  AOP(right)->aopu.aop_dir);
8150                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8151                                  AOP(left)->aopu.aop_dir,
8152                                  AOP(left)->aopu.aop_dir);
8153                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8154                                  AOP(result)->aopu.aop_dir,
8155                                  AOP(result)->aopu.aop_dir);
8156                 }
8157               }
8158             } else {
8159                 // c = bit | val;
8160                 symbol *tlbl = newiTempLabel(NULL);
8161                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8162
8163
8164                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8165                 if( AOP_TYPE(right) == AOP_ACC) {
8166                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8167                   emitSKPNZ;
8168                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8169                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8170                 }
8171
8172
8173
8174                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8175                     pic16_emitcode(";XXX setb","c");
8176                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8177                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8178                 pic16_toBoolean(right);
8179                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8180                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8181                     jmpTrueOrFalse(ifx, tlbl);
8182                     goto release;
8183                 } else {
8184                     CLRC;
8185                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8186                 }
8187             }
8188         }
8189         // bit = c
8190         // val = c
8191         if(size)
8192             pic16_outBitC(result);
8193         // if(bit | ...)
8194         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8195             genIfxJump(ifx, "c");           
8196         goto release ;
8197     }
8198
8199     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8200     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8201     if((AOP_TYPE(right) == AOP_LIT) &&
8202        (AOP_TYPE(result) == AOP_CRY) &&
8203        (AOP_TYPE(left) != AOP_CRY)){
8204         if(lit){
8205           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8206             // result = 1
8207             if(size)
8208                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8209             else 
8210                 continueIfTrue(ifx);
8211             goto release;
8212         } else {
8213           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8214             // lit = 0, result = boolean(left)
8215             if(size)
8216                 pic16_emitcode(";XXX setb","c");
8217             pic16_toBoolean(right);
8218             if(size){
8219                 symbol *tlbl = newiTempLabel(NULL);
8220                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8221                 CLRC;
8222                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8223             } else {
8224                 genIfxJump (ifx,"a");
8225                 goto release;
8226             }
8227         }
8228         pic16_outBitC(result);
8229         goto release ;
8230     }
8231
8232     /* if left is same as result */
8233     if(pic16_sameRegs(AOP(result),AOP(left))){
8234       int know_W = -1;
8235       for(;size--; offset++,lit>>=8) {
8236         if(AOP_TYPE(right) == AOP_LIT){
8237           if((lit & 0xff) == 0)
8238             /*  or'ing with 0 has no effect */
8239             continue;
8240           else {
8241             int p = pic16_my_powof2(lit & 0xff);
8242             if(p>=0) {
8243               /* only one bit is set in the literal, so use a bsf instruction */
8244               pic16_emitpcode(POC_BSF,
8245                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8246             } else {
8247               if(know_W != (lit & 0xff))
8248                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8249               know_W = lit & 0xff;
8250               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8251             }
8252                     
8253           }
8254         } else {
8255           if (AOP_TYPE(left) == AOP_ACC) {
8256             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8257             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8258           } else {                  
8259             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8260             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8261
8262             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8263             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8264
8265           }
8266         }
8267       }
8268     } else {
8269         // left & result in different registers
8270         if(AOP_TYPE(result) == AOP_CRY){
8271             // result = bit
8272             // if(size), result in bit
8273             // if(!size && ifx), conditional oper: if(left | right)
8274             symbol *tlbl = newiTempLabel(NULL);
8275             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8276             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8277
8278
8279             if(size)
8280                 pic16_emitcode(";XXX setb","c");
8281             while(sizer--){
8282                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8283                 pic16_emitcode(";XXX orl","a,%s",
8284                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8285                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8286                 offset++;
8287             }
8288             if(size){
8289                 CLRC;
8290                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8291                 pic16_outBitC(result);
8292             } else if(ifx)
8293                 jmpTrueOrFalse(ifx, tlbl);
8294         } else for(;(size--);offset++){
8295           // normal case
8296           // result = left & right
8297           if(AOP_TYPE(right) == AOP_LIT){
8298             int t = (lit >> (offset*8)) & 0x0FFL;
8299             switch(t) { 
8300             case 0x00:
8301               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8302               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8303
8304               pic16_emitcode("movf","%s,w",
8305                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8306               pic16_emitcode("movwf","%s",
8307                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8308               break;
8309             default:
8310               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8311               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8312               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8313
8314               pic16_emitcode("movlw","0x%x",t);
8315               pic16_emitcode("iorwf","%s,w",
8316                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8317               pic16_emitcode("movwf","%s",
8318                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8319               
8320             }
8321             continue;
8322           }
8323
8324           // faster than result <- left, anl result,right
8325           // and better if result is SFR
8326           if (AOP_TYPE(left) == AOP_ACC) {
8327             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8328             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8329           } else {
8330             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8331             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8332
8333             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8334             pic16_emitcode("iorwf","%s,w",
8335                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8336           }
8337           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8338           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8339         }
8340     }
8341
8342 release :
8343     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8344     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8345     pic16_freeAsmop(result,NULL,ic,TRUE);     
8346 }
8347
8348 /*-----------------------------------------------------------------*/
8349 /* genXor - code for xclusive or                                   */
8350 /*-----------------------------------------------------------------*/
8351 static void genXor (iCode *ic, iCode *ifx)
8352 {
8353   operand *left, *right, *result;
8354   int size, offset=0;
8355   unsigned long lit = 0L;
8356
8357   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8358
8359   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8360   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8361   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8362
8363   /* if left is a literal & right is not ||
8364      if left needs acc & right does not */
8365   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8366       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8367     operand *tmp = right ;
8368     right = left;
8369     left = tmp;
8370   }
8371
8372   /* if result = right then exchange them */
8373   if(pic16_sameRegs(AOP(result),AOP(right))){
8374     operand *tmp = right ;
8375     right = left;
8376     left = tmp;
8377   }
8378
8379   /* if right is bit then exchange them */
8380   if (AOP_TYPE(right) == AOP_CRY &&
8381       AOP_TYPE(left) != AOP_CRY){
8382     operand *tmp = right ;
8383     right = left;
8384     left = tmp;
8385   }
8386   if(AOP_TYPE(right) == AOP_LIT)
8387     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8388
8389   size = AOP_SIZE(result);
8390
8391   // if(bit ^ yy)
8392   // xx = bit ^ yy;
8393   if (AOP_TYPE(left) == AOP_CRY){
8394     if(AOP_TYPE(right) == AOP_LIT){
8395       // c = bit & literal;
8396       if(lit>>1){
8397         // lit>>1  != 0 => result = 1
8398         if(AOP_TYPE(result) == AOP_CRY){
8399           if(size)
8400             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8401             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8402           else if(ifx)
8403             continueIfTrue(ifx);
8404           goto release;
8405         }
8406         pic16_emitcode("setb","c");
8407       } else{
8408         // lit == (0 or 1)
8409         if(lit == 0){
8410           // lit == 0, result = left
8411           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8412             goto release;
8413           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8414         } else{
8415           // lit == 1, result = not(left)
8416           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8417             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8418             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8419             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8420             goto release;
8421           } else {
8422             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8423             pic16_emitcode("cpl","c");
8424           }
8425         }
8426       }
8427
8428     } else {
8429       // right != literal
8430       symbol *tlbl = newiTempLabel(NULL);
8431       if (AOP_TYPE(right) == AOP_CRY){
8432         // c = bit ^ bit;
8433         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8434       }
8435       else{
8436         int sizer = AOP_SIZE(right);
8437         // c = bit ^ val
8438         // if val>>1 != 0, result = 1
8439         pic16_emitcode("setb","c");
8440         while(sizer){
8441           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8442           if(sizer == 1)
8443             // test the msb of the lsb
8444             pic16_emitcode("anl","a,#0xfe");
8445           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8446           sizer--;
8447         }
8448         // val = (0,1)
8449         pic16_emitcode("rrc","a");
8450       }
8451       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8452       pic16_emitcode("cpl","c");
8453       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8454     }
8455     // bit = c
8456     // val = c
8457     if(size)
8458       pic16_outBitC(result);
8459     // if(bit | ...)
8460     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8461       genIfxJump(ifx, "c");           
8462     goto release ;
8463   }
8464
8465   if(pic16_sameRegs(AOP(result),AOP(left))){
8466     /* if left is same as result */
8467     for(;size--; offset++) {
8468       if(AOP_TYPE(right) == AOP_LIT){
8469         int t  = (lit >> (offset*8)) & 0x0FFL;
8470         if(t == 0x00L)
8471           continue;
8472         else
8473           if (IS_AOP_PREG(left)) {
8474             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8475             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8476             pic16_aopPut(AOP(result),"a",offset);
8477           } else {
8478             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8479             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8480             pic16_emitcode("xrl","%s,%s",
8481                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8482                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8483           }
8484       } else {
8485         if (AOP_TYPE(left) == AOP_ACC)
8486           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8487         else {
8488           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8489           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8490 /*
8491           if (IS_AOP_PREG(left)) {
8492             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8493             pic16_aopPut(AOP(result),"a",offset);
8494           } else
8495             pic16_emitcode("xrl","%s,a",
8496                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8497 */
8498         }
8499       }
8500     }
8501   } else {
8502     // left & result in different registers
8503     if(AOP_TYPE(result) == AOP_CRY){
8504       // result = bit
8505       // if(size), result in bit
8506       // if(!size && ifx), conditional oper: if(left ^ right)
8507       symbol *tlbl = newiTempLabel(NULL);
8508       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8509       if(size)
8510         pic16_emitcode("setb","c");
8511       while(sizer--){
8512         if((AOP_TYPE(right) == AOP_LIT) &&
8513            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8514           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8515         } else {
8516           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8517           pic16_emitcode("xrl","a,%s",
8518                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8519         }
8520         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8521         offset++;
8522       }
8523       if(size){
8524         CLRC;
8525         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8526         pic16_outBitC(result);
8527       } else if(ifx)
8528         jmpTrueOrFalse(ifx, tlbl);
8529     } else for(;(size--);offset++){
8530       // normal case
8531       // result = left & right
8532       if(AOP_TYPE(right) == AOP_LIT){
8533         int t = (lit >> (offset*8)) & 0x0FFL;
8534         switch(t) { 
8535         case 0x00:
8536           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8537           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8538           pic16_emitcode("movf","%s,w",
8539                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8540           pic16_emitcode("movwf","%s",
8541                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8542           break;
8543         case 0xff:
8544           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8545           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8546           pic16_emitcode("comf","%s,w",
8547                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8548           pic16_emitcode("movwf","%s",
8549                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8550           break;
8551         default:
8552           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8553           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8554           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8555           pic16_emitcode("movlw","0x%x",t);
8556           pic16_emitcode("xorwf","%s,w",
8557                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8558           pic16_emitcode("movwf","%s",
8559                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8560
8561         }
8562         continue;
8563       }
8564
8565       // faster than result <- left, anl result,right
8566       // and better if result is SFR
8567       if (AOP_TYPE(left) == AOP_ACC) {
8568         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8569         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8570       } else {
8571         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8572         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8573         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8574         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8575       }
8576       if ( AOP_TYPE(result) != AOP_ACC){
8577         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8578         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8579       }
8580     }
8581   }
8582
8583   release :
8584     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8585   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8586   pic16_freeAsmop(result,NULL,ic,TRUE);     
8587 }
8588
8589 /*-----------------------------------------------------------------*/
8590 /* genInline - write the inline code out                           */
8591 /*-----------------------------------------------------------------*/
8592 static void genInline (iCode *ic)
8593 {
8594   char *buffer, *bp, *bp1;
8595     
8596         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8597
8598         _G.inLine += (!options.asmpeep);
8599
8600         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8601         strcpy(buffer,IC_INLINE(ic));
8602
8603 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8604
8605         /* emit each line as a code */
8606         while (*bp) {
8607                 if (*bp == '\n') {
8608                         *bp++ = '\0';
8609
8610                         if(*bp1)
8611                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8612                         bp1 = bp;
8613                 } else {
8614                         if (*bp == ':') {
8615                                 bp++;
8616                                 *bp = '\0';
8617                                 bp++;
8618
8619                                 /* print label, use this special format with NULL directive
8620                                  * to denote that the argument should not be indented with tab */
8621                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8622                                 bp1 = bp;
8623                         } else
8624                                 bp++;
8625                 }
8626         }
8627
8628         if ((bp1 != bp) && *bp1)
8629                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8630
8631
8632     Safe_free(buffer);
8633
8634     _G.inLine -= (!options.asmpeep);
8635 }
8636
8637 /*-----------------------------------------------------------------*/
8638 /* genRRC - rotate right with carry                                */
8639 /*-----------------------------------------------------------------*/
8640 static void genRRC (iCode *ic)
8641 {
8642   operand *left , *result ;
8643   int size, offset = 0, same;
8644
8645   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8646
8647   /* rotate right with carry */
8648   left = IC_LEFT(ic);
8649   result=IC_RESULT(ic);
8650   pic16_aopOp (left,ic,FALSE);
8651   pic16_aopOp (result,ic,FALSE);
8652
8653   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8654
8655   same = pic16_sameRegs(AOP(result),AOP(left));
8656
8657   size = AOP_SIZE(result);    
8658
8659   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8660
8661   /* get the lsb and put it into the carry */
8662   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8663
8664   offset = 0 ;
8665
8666   while(size--) {
8667
8668     if(same) {
8669       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8670     } else {
8671       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8672       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8673     }
8674
8675     offset++;
8676   }
8677
8678   pic16_freeAsmop(left,NULL,ic,TRUE);
8679   pic16_freeAsmop(result,NULL,ic,TRUE);
8680 }
8681
8682 /*-----------------------------------------------------------------*/
8683 /* genRLC - generate code for rotate left with carry               */
8684 /*-----------------------------------------------------------------*/
8685 static void genRLC (iCode *ic)
8686 {    
8687   operand *left , *result ;
8688   int size, offset = 0;
8689   int same;
8690
8691   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8692   /* rotate right with carry */
8693   left = IC_LEFT(ic);
8694   result=IC_RESULT(ic);
8695   pic16_aopOp (left,ic,FALSE);
8696   pic16_aopOp (result,ic,FALSE);
8697
8698   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8699
8700   same = pic16_sameRegs(AOP(result),AOP(left));
8701
8702   /* move it to the result */
8703   size = AOP_SIZE(result);    
8704
8705   /* get the msb and put it into the carry */
8706   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8707
8708   offset = 0 ;
8709
8710   while(size--) {
8711
8712     if(same) {
8713       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8714     } else {
8715       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8716       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8717     }
8718
8719     offset++;
8720   }
8721
8722
8723   pic16_freeAsmop(left,NULL,ic,TRUE);
8724   pic16_freeAsmop(result,NULL,ic,TRUE);
8725 }
8726
8727
8728 /* gpasm can get the highest order bit with HIGH/UPPER
8729  * so the following probably is not needed -- VR */
8730  
8731 /*-----------------------------------------------------------------*/
8732 /* genGetHbit - generates code get highest order bit               */
8733 /*-----------------------------------------------------------------*/
8734 static void genGetHbit (iCode *ic)
8735 {
8736     operand *left, *result;
8737     left = IC_LEFT(ic);
8738     result=IC_RESULT(ic);
8739     pic16_aopOp (left,ic,FALSE);
8740     pic16_aopOp (result,ic,FALSE);
8741
8742     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8743     /* get the highest order byte into a */
8744     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8745     if(AOP_TYPE(result) == AOP_CRY){
8746         pic16_emitcode("rlc","a");
8747         pic16_outBitC(result);
8748     }
8749     else{
8750         pic16_emitcode("rl","a");
8751         pic16_emitcode("anl","a,#0x01");
8752         pic16_outAcc(result);
8753     }
8754
8755
8756     pic16_freeAsmop(left,NULL,ic,TRUE);
8757     pic16_freeAsmop(result,NULL,ic,TRUE);
8758 }
8759
8760 #if 0
8761 /*-----------------------------------------------------------------*/
8762 /* AccRol - rotate left accumulator by known count                 */
8763 /*-----------------------------------------------------------------*/
8764 static void AccRol (int shCount)
8765 {
8766     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8767     shCount &= 0x0007;              // shCount : 0..7
8768     switch(shCount){
8769         case 0 :
8770             break;
8771         case 1 :
8772             pic16_emitcode("rl","a");
8773             break;
8774         case 2 :
8775             pic16_emitcode("rl","a");
8776             pic16_emitcode("rl","a");
8777             break;
8778         case 3 :
8779             pic16_emitcode("swap","a");
8780             pic16_emitcode("rr","a");
8781             break;
8782         case 4 :
8783             pic16_emitcode("swap","a");
8784             break;
8785         case 5 :
8786             pic16_emitcode("swap","a");
8787             pic16_emitcode("rl","a");
8788             break;
8789         case 6 :
8790             pic16_emitcode("rr","a");
8791             pic16_emitcode("rr","a");
8792             break;
8793         case 7 :
8794             pic16_emitcode("rr","a");
8795             break;
8796     }
8797 }
8798 #endif
8799
8800 /*-----------------------------------------------------------------*/
8801 /* AccLsh - left shift accumulator by known count                  */
8802 /*-----------------------------------------------------------------*/
8803 static void AccLsh (int shCount)
8804 {
8805         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8806         switch(shCount){
8807                 case 0 :
8808                         return;
8809                         break;
8810                 case 1 :
8811                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812                         break;
8813                 case 2 :
8814                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8816                         break;
8817                 case 3 :
8818                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8820                         break;
8821                 case 4 :
8822                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8823                         break;
8824                 case 5 :
8825                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8826                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827                         break;
8828                 case 6 :
8829                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8831                         break;
8832                 case 7 :
8833                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8834                         break;
8835         }
8836
8837         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8838 }
8839
8840 /*-----------------------------------------------------------------*/
8841 /* AccRsh - right shift accumulator by known count                 */
8842 /*-----------------------------------------------------------------*/
8843 static void AccRsh (int shCount, int andmask)
8844 {
8845         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8846         switch(shCount){
8847                 case 0 :
8848                         return; break;
8849                 case 1 :
8850                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8851                         break;
8852                 case 2 :
8853                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8854                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8855                         break;
8856                 case 3 :
8857                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8858                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8859                         break;
8860                 case 4 :
8861                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8862                         break;
8863                 case 5 :
8864                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8865                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8866                         break;
8867                 case 6 :
8868                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8869                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8870                         break;
8871                 case 7 :
8872                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8873                         break;
8874         }
8875         
8876         if(andmask)
8877                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8878         else
8879                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8880 }
8881
8882 #if 0
8883 /*-----------------------------------------------------------------*/
8884 /* AccSRsh - signed right shift accumulator by known count                 */
8885 /*-----------------------------------------------------------------*/
8886 static void AccSRsh (int shCount)
8887 {
8888     symbol *tlbl ;
8889     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8890     if(shCount != 0){
8891         if(shCount == 1){
8892             pic16_emitcode("mov","c,acc.7");
8893             pic16_emitcode("rrc","a");
8894         } else if(shCount == 2){
8895             pic16_emitcode("mov","c,acc.7");
8896             pic16_emitcode("rrc","a");
8897             pic16_emitcode("mov","c,acc.7");
8898             pic16_emitcode("rrc","a");
8899         } else {
8900             tlbl = newiTempLabel(NULL);
8901             /* rotate right accumulator */
8902             AccRol(8 - shCount);
8903             /* and kill the higher order bits */
8904             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8905             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8906             pic16_emitcode("orl","a,#0x%02x",
8907                      (unsigned char)~SRMask[shCount]);
8908             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8909         }
8910     }
8911 }
8912 #endif
8913
8914 /*-----------------------------------------------------------------*/
8915 /* shiftR1Left2Result - shift right one byte from left to result   */
8916 /*-----------------------------------------------------------------*/
8917 static void shiftR1Left2ResultSigned (operand *left, int offl,
8918                                 operand *result, int offr,
8919                                 int shCount)
8920 {
8921   int same;
8922
8923   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8924
8925   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8926
8927   switch(shCount) {
8928   case 1:
8929     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8930     if(same) 
8931       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8932     else {
8933       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8934       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8935     }
8936
8937     break;
8938   case 2:
8939
8940     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8941     if(same) 
8942       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8943     else {
8944       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8945       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8946     }
8947     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8948     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8949
8950     break;
8951
8952   case 3:
8953     if(same)
8954       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8955     else {
8956       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8957       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8958     }
8959
8960     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8961     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8962     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8963
8964     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8965     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8966
8967     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8968     break;
8969
8970   case 4:
8971     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8972     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8973     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8974     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8975     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8976     break;
8977   case 5:
8978     if(same) {
8979       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8980     } else {
8981       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8982       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8983     }
8984     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8985     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8986     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8987     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8988     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8989     break;
8990
8991   case 6:
8992     if(same) {
8993       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8994       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8995       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8996       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8997       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8998       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8999     } else {
9000       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9001       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9002       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9003       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9004       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9005     }
9006     break;
9007
9008   case 7:
9009     if(same) {
9010       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9011       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9012       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9013       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014     } else {
9015       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9016       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9017       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
9018     }
9019
9020   default:
9021     break;
9022   }
9023 }
9024
9025 /*-----------------------------------------------------------------*/
9026 /* shiftR1Left2Result - shift right one byte from left to result   */
9027 /*-----------------------------------------------------------------*/
9028 static void shiftR1Left2Result (operand *left, int offl,
9029                                 operand *result, int offr,
9030                                 int shCount, int sign)
9031 {
9032   int same;
9033
9034   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9035
9036   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9037
9038   /* Copy the msb into the carry if signed. */
9039   if(sign) {
9040     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9041     return;
9042   }
9043
9044
9045
9046   switch(shCount) {
9047   case 1:
9048     emitCLRC;
9049     if(same) 
9050       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9051     else {
9052       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9053       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9054     }
9055     break;
9056   case 2:
9057     emitCLRC;
9058     if(same) {
9059       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9060     } else {
9061       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9062       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9063     }
9064     emitCLRC;
9065     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9066
9067     break;
9068   case 3:
9069     if(same)
9070       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9071     else {
9072       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9073       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9074     }
9075
9076     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9077     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9078     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9079     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9080     break;
9081       
9082   case 4:
9083     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9084     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9085     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9086     break;
9087
9088   case 5:
9089     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9090     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9091     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9092     //emitCLRC;
9093     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9094
9095     break;
9096   case 6:
9097
9098     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9099     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9100     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9101     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9102     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9103     break;
9104
9105   case 7:
9106
9107     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9108     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9109     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9110
9111     break;
9112
9113   default:
9114     break;
9115   }
9116 }
9117
9118 /*-----------------------------------------------------------------*/
9119 /* shiftL1Left2Result - shift left one byte from left to result    */
9120 /*-----------------------------------------------------------------*/
9121 static void shiftL1Left2Result (operand *left, int offl,
9122                                 operand *result, int offr, int shCount)
9123 {
9124   int same;
9125
9126   //    char *l;
9127   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9128
9129   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9130   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9131     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9132     //    MOVA(l);
9133     /* shift left accumulator */
9134     //AccLsh(shCount); // don't comment out just yet...
9135   //    pic16_aopPut(AOP(result),"a",offr);
9136
9137   switch(shCount) {
9138   case 1:
9139     /* Shift left 1 bit position */
9140     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9141     if(same) {
9142       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9143     } else {
9144       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9145       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9146     }
9147     break;
9148   case 2:
9149     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9150     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9151     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9152     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9153     break;
9154   case 3:
9155     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9156     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9157     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9158     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9159     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9160     break;
9161   case 4:
9162     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9163     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9164     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9165     break;
9166   case 5:
9167     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9168     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9169     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9170     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9171     break;
9172   case 6:
9173     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9174     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9175     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9176     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9177     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9178     break;
9179   case 7:
9180     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9181     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9182     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9183     break;
9184
9185   default:
9186     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9187   }
9188
9189 }
9190
9191 /*-----------------------------------------------------------------*/
9192 /* movLeft2Result - move byte from left to result                  */
9193 /*-----------------------------------------------------------------*/
9194 static void movLeft2Result (operand *left, int offl,
9195                             operand *result, int offr)
9196 {
9197   char *l;
9198   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9199   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9200     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9201
9202     if (*l == '@' && (IS_AOP_PREG(result))) {
9203       pic16_emitcode("mov","a,%s",l);
9204       pic16_aopPut(AOP(result),"a",offr);
9205     } else {
9206       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9207       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9208     }
9209   }
9210 }
9211
9212 /*-----------------------------------------------------------------*/
9213 /* shiftL2Left2Result - shift left two bytes from left to result   */
9214 /*-----------------------------------------------------------------*/
9215 static void shiftL2Left2Result (operand *left, int offl,
9216                                 operand *result, int offr, int shCount)
9217 {
9218   int same = pic16_sameRegs(AOP(result), AOP(left));
9219   int i;
9220
9221   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9222
9223   if (same && (offl != offr)) { // shift bytes
9224     if (offr > offl) {
9225        for(i=1;i>-1;i--) {
9226          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9227          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9228        }
9229     } else { // just treat as different later on
9230                 same = 0;
9231     }
9232   }
9233
9234   if(same) {
9235     switch(shCount) {
9236     case 0:
9237       break;
9238     case 1:
9239     case 2:
9240     case 3:
9241
9242       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9243       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9244       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9245
9246       while(--shCount) {
9247                 emitCLRC;
9248                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9249                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9250       }
9251
9252       break;
9253     case 4:
9254     case 5:
9255       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9256       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9257       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9258       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9259       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9260       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9261       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9262       if(shCount >=5) {
9263                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9264                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9265       }
9266       break;
9267     case 6:
9268       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9269       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9270       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9271       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9272       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9273       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9274       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9275       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9276       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9277       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9278       break;
9279     case 7:
9280       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9281       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9282       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9283       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9284       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9285     }
9286
9287   } else {
9288     switch(shCount) {
9289     case 0:
9290       break;
9291     case 1:
9292     case 2:
9293     case 3:
9294       /* note, use a mov/add for the shift since the mov has a
9295          chance of getting optimized out */
9296       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9297       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9298       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9299       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9300       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9301
9302       while(--shCount) {
9303                 emitCLRC;
9304                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9305                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9306       }
9307       break;
9308
9309     case 4:
9310     case 5:
9311       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9312       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9313       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9314       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9315       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9316       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9317       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9318       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9319
9320
9321       if(shCount == 5) {
9322                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9323                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9324       }
9325       break;
9326     case 6:
9327       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9328       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9329       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9330       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9331
9332       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9333       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9334       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9335       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9336       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9337       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9338       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9339       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9340       break;
9341     case 7:
9342       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9343       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9344       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9345       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9346       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9347     }
9348   }
9349
9350 }
9351 /*-----------------------------------------------------------------*/
9352 /* shiftR2Left2Result - shift right two bytes from left to result  */
9353 /*-----------------------------------------------------------------*/
9354 static void shiftR2Left2Result (operand *left, int offl,
9355                                 operand *result, int offr,
9356                                 int shCount, int sign)
9357 {
9358   int same = pic16_sameRegs(AOP(result), AOP(left));
9359   int i;
9360   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9361
9362   if (same && (offl != offr)) { // shift right bytes
9363     if (offr < offl) {
9364        for(i=0;i<2;i++) {
9365          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9366          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9367        }
9368     } else { // just treat as different later on
9369                 same = 0;
9370     }
9371   }
9372
9373   switch(shCount) {
9374   case 0:
9375     break;
9376   case 1:
9377   case 2:
9378   case 3:
9379     if(sign)
9380       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9381     else
9382       emitCLRC;
9383
9384     if(same) {
9385       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9386       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9387     } else {
9388       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9389       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9390       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9391       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9392     }
9393
9394     while(--shCount) {
9395       if(sign)
9396                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9397       else
9398                 emitCLRC;
9399       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9400       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9401     }
9402     break;
9403   case 4:
9404   case 5:
9405     if(same) {
9406
9407       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9408       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9409       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9410
9411       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9412       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9413       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9414       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9415     } else {
9416       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9417       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9418       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9419
9420       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9421       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9422       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9423       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9424       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9425     }
9426
9427     if(shCount >=5) {
9428       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9429       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9430     }
9431
9432     if(sign) {
9433       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9434       pic16_emitpcode(POC_BTFSC, 
9435                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9436       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9437     }
9438
9439     break;
9440
9441   case 6:
9442     if(same) {
9443
9444       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9445       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9446
9447       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9448       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9449       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9450       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9451       if(sign) {
9452         pic16_emitpcode(POC_BTFSC, 
9453                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9454         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9455       }
9456       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9457       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9458       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9459       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9460     } else {
9461       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9462       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9463       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9464       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9465       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9466       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9467       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9468       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9469       if(sign) {
9470         pic16_emitpcode(POC_BTFSC, 
9471                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9472         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9473       }
9474       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9475       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9476
9477         
9478     }
9479
9480     break;
9481   case 7:
9482     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9483     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9484     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9485     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9486     if(sign) {
9487       emitSKPNC;
9488       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9489     } else 
9490       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9491   }
9492 }
9493
9494
9495 /*-----------------------------------------------------------------*/
9496 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9497 /*-----------------------------------------------------------------*/
9498 static void shiftLLeftOrResult (operand *left, int offl,
9499                                 operand *result, int offr, int shCount)
9500 {
9501     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9502
9503     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9504     /* shift left accumulator */
9505     AccLsh(shCount);
9506     /* or with result */
9507     /* back to result */
9508     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9509 }
9510
9511 /*-----------------------------------------------------------------*/
9512 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9513 /*-----------------------------------------------------------------*/
9514 static void shiftRLeftOrResult (operand *left, int offl,
9515                                 operand *result, int offr, int shCount)
9516 {
9517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9518     
9519     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9520     /* shift right accumulator */
9521     AccRsh(shCount, 1);
9522     /* or with result */
9523     /* back to result */
9524     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9525 }
9526
9527 /*-----------------------------------------------------------------*/
9528 /* genlshOne - left shift a one byte quantity by known count       */
9529 /*-----------------------------------------------------------------*/
9530 static void genlshOne (operand *result, operand *left, int shCount)
9531 {       
9532     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9534 }
9535
9536 /*-----------------------------------------------------------------*/
9537 /* genlshTwo - left shift two bytes by known amount != 0           */
9538 /*-----------------------------------------------------------------*/
9539 static void genlshTwo (operand *result,operand *left, int shCount)
9540 {
9541     int size;
9542     
9543     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9544     size = pic16_getDataSize(result);
9545
9546     /* if shCount >= 8 */
9547     if (shCount >= 8) {
9548         shCount -= 8 ;
9549
9550         if (size > 1){
9551             if (shCount)
9552                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9553             else 
9554                 movLeft2Result(left, LSB, result, MSB16);
9555         }
9556         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9557     }
9558
9559     /*  1 <= shCount <= 7 */
9560     else {  
9561         if(size == 1)
9562             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9563         else 
9564             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9565     }
9566 }
9567
9568 /*-----------------------------------------------------------------*/
9569 /* shiftLLong - shift left one long from left to result            */
9570 /* offr = LSB or MSB16                                             */
9571 /*-----------------------------------------------------------------*/
9572 static void shiftLLong (operand *left, operand *result, int offr )
9573 {
9574     int size = AOP_SIZE(result);
9575     int same = pic16_sameRegs(AOP(left),AOP(result));
9576         int i;
9577
9578     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9579
9580         if (same && (offr == MSB16)) { //shift one byte
9581                 for(i=size-1;i>=MSB16;i--) {
9582                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9583                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9584                 }
9585         } else {
9586                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9587         }
9588         
9589     if (size > LSB+offr ){
9590                 if (same) {
9591                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9592                 } else {
9593                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9594                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9595                 }
9596          }
9597
9598     if(size > MSB16+offr){
9599                 if (same) {
9600                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9601                 } else {
9602                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9603                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9604                 }
9605     }
9606
9607     if(size > MSB24+offr){
9608                 if (same) {
9609                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9610                 } else {
9611                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9612                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9613                 }
9614     }
9615
9616     if(size > MSB32+offr){
9617                 if (same) {
9618                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9619                 } else {
9620                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9621                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9622                 }
9623     }
9624     if(offr != LSB)
9625                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9626
9627 }
9628
9629 /*-----------------------------------------------------------------*/
9630 /* genlshFour - shift four byte by a known amount != 0             */
9631 /*-----------------------------------------------------------------*/
9632 static void genlshFour (operand *result, operand *left, int shCount)
9633 {
9634     int size;
9635
9636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9637     size = AOP_SIZE(result);
9638
9639     /* if shifting more that 3 bytes */
9640     if (shCount >= 24 ) {
9641         shCount -= 24;
9642         if (shCount)
9643             /* lowest order of left goes to the highest
9644             order of the destination */
9645             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9646         else
9647             movLeft2Result(left, LSB, result, MSB32);
9648
9649                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9650                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9651                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9652
9653         return;
9654     }
9655
9656     /* more than two bytes */
9657     else if ( shCount >= 16 ) {
9658         /* lower order two bytes goes to higher order two bytes */
9659         shCount -= 16;
9660         /* if some more remaining */
9661         if (shCount)
9662             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9663         else {
9664             movLeft2Result(left, MSB16, result, MSB32);
9665             movLeft2Result(left, LSB, result, MSB24);
9666         }
9667                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9669         return;
9670     }    
9671
9672     /* if more than 1 byte */
9673     else if ( shCount >= 8 ) {
9674         /* lower order three bytes goes to higher order  three bytes */
9675         shCount -= 8;
9676         if(size == 2){
9677             if(shCount)
9678                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9679             else
9680                 movLeft2Result(left, LSB, result, MSB16);
9681         }
9682         else{   /* size = 4 */
9683             if(shCount == 0){
9684                 movLeft2Result(left, MSB24, result, MSB32);
9685                 movLeft2Result(left, MSB16, result, MSB24);
9686                 movLeft2Result(left, LSB, result, MSB16);
9687                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9688             }
9689             else if(shCount == 1)
9690                 shiftLLong(left, result, MSB16);
9691             else{
9692                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9693                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9694                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9695                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9696             }
9697         }
9698     }
9699
9700     /* 1 <= shCount <= 7 */
9701     else if(shCount <= 3)
9702     { 
9703         shiftLLong(left, result, LSB);
9704         while(--shCount >= 1)
9705             shiftLLong(result, result, LSB);
9706     }
9707     /* 3 <= shCount <= 7, optimize */
9708     else{
9709         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9710         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9711         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9712     }
9713 }
9714
9715 /*-----------------------------------------------------------------*/
9716 /* genLeftShiftLiteral - left shifting by known count              */
9717 /*-----------------------------------------------------------------*/
9718 void pic16_genLeftShiftLiteral (operand *left,
9719                                  operand *right,
9720                                  operand *result,
9721                                  iCode *ic)
9722 {    
9723     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9724     int size;
9725
9726     FENTRY;
9727     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9728     pic16_freeAsmop(right,NULL,ic,TRUE);
9729
9730     pic16_aopOp(left,ic,FALSE);
9731     pic16_aopOp(result,ic,FALSE);
9732
9733     size = getSize(operandType(result));
9734
9735 #if VIEW_SIZE
9736     pic16_emitcode("; shift left ","result %d, left %d",size,
9737              AOP_SIZE(left));
9738 #endif
9739
9740     /* I suppose that the left size >= result size */
9741     if(shCount == 0){
9742         while(size--){
9743             movLeft2Result(left, size, result, size);
9744         }
9745     }
9746
9747     else if(shCount >= (size * 8))
9748         while(size--)
9749             pic16_aopPut(AOP(result),zero,size);
9750     else{
9751         switch (size) {
9752             case 1:
9753                 genlshOne (result,left,shCount);
9754                 break;
9755
9756             case 2:
9757             case 3:
9758                 genlshTwo (result,left,shCount);
9759                 break;
9760
9761             case 4:
9762                 genlshFour (result,left,shCount);
9763                 break;
9764         }
9765     }
9766     pic16_freeAsmop(left,NULL,ic,TRUE);
9767     pic16_freeAsmop(result,NULL,ic,TRUE);
9768 }
9769
9770 /*-----------------------------------------------------------------*
9771  * genMultiAsm - repeat assembly instruction for size of register.
9772  * if endian == 1, then the high byte (i.e base address + size of 
9773  * register) is used first else the low byte is used first;
9774  *-----------------------------------------------------------------*/
9775 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9776 {
9777
9778   int offset = 0;
9779
9780   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9781
9782   if(!reg)
9783     return;
9784
9785   if(!endian) {
9786     endian = 1;
9787   } else {
9788     endian = -1;
9789     offset = size-1;
9790   }
9791
9792   while(size--) {
9793     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9794     offset += endian;
9795   }
9796
9797 }
9798
9799 #if !(USE_GENERIC_SIGNED_SHIFT)
9800 /*-----------------------------------------------------------------*/
9801 /* genLeftShift - generates code for left shifting                 */
9802 /*-----------------------------------------------------------------*/
9803 static void genLeftShift (iCode *ic)
9804 {
9805   operand *left,*right, *result;
9806   int size, offset;
9807 //  char *l;
9808   symbol *tlbl , *tlbl1;
9809   pCodeOp *pctemp;
9810
9811   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9812
9813   right = IC_RIGHT(ic);
9814   left  = IC_LEFT(ic);
9815   result = IC_RESULT(ic);
9816
9817   pic16_aopOp(right,ic,FALSE);
9818
9819   /* if the shift count is known then do it 
9820      as efficiently as possible */
9821   if (AOP_TYPE(right) == AOP_LIT) {
9822     pic16_genLeftShiftLiteral (left,right,result,ic);
9823     return ;
9824   }
9825
9826   /* shift count is unknown then we have to form
9827    * a loop. Get the loop count in WREG : Note: we take
9828    * only the lower order byte since shifting
9829    * more than 32 bits make no sense anyway, ( the
9830    * largest size of an object can be only 32 bits ) */
9831   
9832   pic16_aopOp(left,ic,FALSE);
9833   pic16_aopOp(result,ic,FALSE);
9834
9835   /* now move the left to the result if they are not the
9836    * same, and if size > 1,
9837    * and if right is not same to result (!!!) -- VR */
9838   if (!pic16_sameRegs(AOP(left),AOP(result))
9839       && (AOP_SIZE(result) > 1)) {
9840
9841     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9842
9843     size = AOP_SIZE(result);
9844     offset=0;
9845     while (size--) {
9846
9847 #if 0
9848       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9849       if (*l == '@' && (IS_AOP_PREG(result))) {
9850
9851           pic16_emitcode("mov","a,%s",l);
9852           pic16_aopPut(AOP(result),"a",offset);
9853       } else
9854 #endif
9855       {
9856         /* we don't know if left is a literal or a register, take care -- VR */
9857         mov2f(AOP(result), AOP(left), offset);
9858       }
9859       offset++;
9860     }
9861   }
9862
9863   size = AOP_SIZE(result);
9864
9865   /* if it is only one byte then */
9866   if (size == 1) {
9867     if(optimized_for_speed) {
9868       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9869       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9870       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9871       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9872       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9873       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9874       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9875       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9876       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9877       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9878       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9879       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9880     } else {
9881
9882       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9883
9884       tlbl = newiTempLabel(NULL);
9885
9886 #if 1
9887       /* this is already done, why change it? */
9888       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9889                 mov2f(AOP(result), AOP(left), 0);
9890       }
9891 #endif
9892
9893       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9894       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9895       pic16_emitpLabel(tlbl->key);
9896       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9897       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9898       emitSKPC;
9899       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9900     }
9901     goto release ;
9902   }
9903     
9904   if (pic16_sameRegs(AOP(left),AOP(result))) {
9905
9906     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9907     
9908     tlbl = newiTempLabel(NULL);
9909     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9910     genMultiAsm(POC_RRCF, result, size,1);
9911     pic16_emitpLabel(tlbl->key);
9912     genMultiAsm(POC_RLCF, result, size,0);
9913     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9914     emitSKPC;
9915     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9916     goto release;
9917   }
9918
9919   //tlbl = newiTempLabel(NULL);
9920   //offset = 0 ;   
9921   //tlbl1 = newiTempLabel(NULL);
9922
9923   //reAdjustPreg(AOP(result));    
9924     
9925   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9926   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9927   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9928   //MOVA(l);
9929   //pic16_emitcode("add","a,acc");         
9930   //pic16_aopPut(AOP(result),"a",offset++);
9931   //while (--size) {
9932   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9933   //  MOVA(l);
9934   //  pic16_emitcode("rlc","a");         
9935   //  pic16_aopPut(AOP(result),"a",offset++);
9936   //}
9937   //reAdjustPreg(AOP(result));
9938
9939   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9940   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9941
9942
9943   tlbl = newiTempLabel(NULL);
9944   tlbl1= newiTempLabel(NULL);
9945
9946   size = AOP_SIZE(result);
9947   offset = 1;
9948
9949   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9950
9951   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9952
9953   /* offset should be 0, 1 or 3 */
9954   
9955   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9956   emitSKPNZ;
9957   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9958
9959   pic16_emitpcode(POC_MOVWF, pctemp);
9960
9961
9962   pic16_emitpLabel(tlbl->key);
9963
9964   emitCLRC;
9965   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9966   while(--size)
9967     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9968
9969   pic16_emitpcode(POC_DECFSZ,  pctemp);
9970   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9971   pic16_emitpLabel(tlbl1->key);
9972
9973   pic16_popReleaseTempReg(pctemp,1);
9974
9975
9976  release:
9977   pic16_freeAsmop (right,NULL,ic,TRUE);
9978   pic16_freeAsmop(left,NULL,ic,TRUE);
9979   pic16_freeAsmop(result,NULL,ic,TRUE);
9980 }
9981 #endif
9982
9983
9984 #if 0
9985 #error old code (left here for reference)
9986 /*-----------------------------------------------------------------*/
9987 /* genLeftShift - generates code for left shifting                 */
9988 /*-----------------------------------------------------------------*/
9989 static void genLeftShift (iCode *ic)
9990 {
9991   operand *left,*right, *result;
9992   int size, offset;
9993   char *l;
9994   symbol *tlbl , *tlbl1;
9995   pCodeOp *pctemp;
9996
9997   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9998
9999   right = IC_RIGHT(ic);
10000   left  = IC_LEFT(ic);
10001   result = IC_RESULT(ic);
10002
10003   pic16_aopOp(right,ic,FALSE);
10004
10005   /* if the shift count is known then do it 
10006      as efficiently as possible */
10007   if (AOP_TYPE(right) == AOP_LIT) {
10008     pic16_genLeftShiftLiteral (left,right,result,ic);
10009     return ;
10010   }
10011
10012   /* shift count is unknown then we have to form 
10013      a loop get the loop count in B : Note: we take
10014      only the lower order byte since shifting
10015      more that 32 bits make no sense anyway, ( the
10016      largest size of an object can be only 32 bits ) */  
10017
10018     
10019   pic16_aopOp(left,ic,FALSE);
10020   pic16_aopOp(result,ic,FALSE);
10021
10022   /* now move the left to the result if they are not the
10023      same */
10024   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10025       AOP_SIZE(result) > 1) {
10026
10027     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10028
10029     size = AOP_SIZE(result);
10030     offset=0;
10031     while (size--) {
10032       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10033       if (*l == '@' && (IS_AOP_PREG(result))) {
10034
10035         pic16_emitcode("mov","a,%s",l);
10036         pic16_aopPut(AOP(result),"a",offset);
10037       } else {
10038
10039         /* we don't know if left is a literal or a register, take care -- VR */
10040         mov2f(AOP(result), AOP(left), offset);
10041       }
10042       offset++;
10043     }
10044   }
10045
10046   size = AOP_SIZE(result);
10047
10048   /* if it is only one byte then */
10049   if (size == 1) {
10050     if(optimized_for_speed) {
10051       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10052       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10053       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10054       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10055       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10056       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10057       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10058       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10059       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10060       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10061       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10062       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10063     } else {
10064
10065       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10066
10067       tlbl = newiTempLabel(NULL);
10068       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10069                 mov2f(AOP(result), AOP(left), 0);
10070                 
10071 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10072 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10073       }
10074
10075       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10076       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10077       pic16_emitpLabel(tlbl->key);
10078       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10079       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10080       emitSKPC;
10081       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10082     }
10083     goto release ;
10084   }
10085     
10086   if (pic16_sameRegs(AOP(left),AOP(result))) {
10087
10088     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10089     
10090     tlbl = newiTempLabel(NULL);
10091     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10092     genMultiAsm(POC_RRCF, result, size,1);
10093     pic16_emitpLabel(tlbl->key);
10094     genMultiAsm(POC_RLCF, result, size,0);
10095     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10096     emitSKPC;
10097     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10098     goto release;
10099   }
10100
10101   //tlbl = newiTempLabel(NULL);
10102   //offset = 0 ;   
10103   //tlbl1 = newiTempLabel(NULL);
10104
10105   //reAdjustPreg(AOP(result));    
10106     
10107   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10108   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10109   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10110   //MOVA(l);
10111   //pic16_emitcode("add","a,acc");         
10112   //pic16_aopPut(AOP(result),"a",offset++);
10113   //while (--size) {
10114   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10115   //  MOVA(l);
10116   //  pic16_emitcode("rlc","a");         
10117   //  pic16_aopPut(AOP(result),"a",offset++);
10118   //}
10119   //reAdjustPreg(AOP(result));
10120
10121   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10122   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10123
10124
10125   tlbl = newiTempLabel(NULL);
10126   tlbl1= newiTempLabel(NULL);
10127
10128   size = AOP_SIZE(result);
10129   offset = 1;
10130
10131   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10132
10133   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10134
10135   /* offset should be 0, 1 or 3 */
10136   
10137   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10138   emitSKPNZ;
10139   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10140
10141   pic16_emitpcode(POC_MOVWF, pctemp);
10142
10143
10144   pic16_emitpLabel(tlbl->key);
10145
10146   emitCLRC;
10147   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10148   while(--size)
10149     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10150
10151   pic16_emitpcode(POC_DECFSZ,  pctemp);
10152   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10153   pic16_emitpLabel(tlbl1->key);
10154
10155   pic16_popReleaseTempReg(pctemp,1);
10156
10157
10158  release:
10159   pic16_freeAsmop (right,NULL,ic,TRUE);
10160   pic16_freeAsmop(left,NULL,ic,TRUE);
10161   pic16_freeAsmop(result,NULL,ic,TRUE);
10162 }
10163 #endif
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genrshOne - right shift a one byte quantity by known count      */
10167 /*-----------------------------------------------------------------*/
10168 static void genrshOne (operand *result, operand *left,
10169                        int shCount, int sign)
10170 {
10171     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10172     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10173 }
10174
10175 /*-----------------------------------------------------------------*/
10176 /* genrshTwo - right shift two bytes by known amount != 0          */
10177 /*-----------------------------------------------------------------*/
10178 static void genrshTwo (operand *result,operand *left,
10179                        int shCount, int sign)
10180 {
10181   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10182   /* if shCount >= 8 */
10183   if (shCount >= 8) {
10184     shCount -= 8 ;
10185     if (shCount)
10186       shiftR1Left2Result(left, MSB16, result, LSB,
10187                          shCount, sign);
10188     else
10189       movLeft2Result(left, MSB16, result, LSB);
10190
10191     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10192
10193     if(sign) {
10194       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10195       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10196     }
10197   }
10198
10199   /*  1 <= shCount <= 7 */
10200   else
10201     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10202 }
10203
10204 /*-----------------------------------------------------------------*/
10205 /* shiftRLong - shift right one long from left to result           */
10206 /* offl = LSB or MSB16                                             */
10207 /*-----------------------------------------------------------------*/
10208 static void shiftRLong (operand *left, int offl,
10209                         operand *result, int sign)
10210 {
10211     int size = AOP_SIZE(result);
10212     int same = pic16_sameRegs(AOP(left),AOP(result));
10213     int i;
10214     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10215
10216         if (same && (offl == MSB16)) { //shift one byte right
10217                 for(i=MSB16;i<size;i++) {
10218                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10219                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10220                 }
10221         }
10222
10223     if(sign)
10224                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10225         else
10226                 emitCLRC;
10227
10228         if (same) {
10229                 if (offl == LSB)
10230                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10231         } else {
10232         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10233         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10234         }
10235
10236     if(offl == MSB16) {
10237         /* add sign of "a" */
10238         pic16_addSign(result, MSB32, sign);
10239         }
10240
10241         if (same) {
10242         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10243         } else {
10244         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10245         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10246         }
10247         
10248         if (same) {
10249         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10250         } else {
10251         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10252         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10253         }
10254
10255         if (same) {
10256         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10257         } else {
10258         if(offl == LSB){
10259                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10260                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10261         }
10262         }
10263 }
10264
10265 /*-----------------------------------------------------------------*/
10266 /* genrshFour - shift four byte by a known amount != 0             */
10267 /*-----------------------------------------------------------------*/
10268 static void genrshFour (operand *result, operand *left,
10269                         int shCount, int sign)
10270 {
10271   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10272   /* if shifting more that 3 bytes */
10273   if(shCount >= 24 ) {
10274     shCount -= 24;
10275     if(shCount)
10276       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10277     else
10278       movLeft2Result(left, MSB32, result, LSB);
10279
10280     pic16_addSign(result, MSB16, sign);
10281   }
10282   else if(shCount >= 16){
10283     shCount -= 16;
10284     if(shCount)
10285       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10286     else{
10287       movLeft2Result(left, MSB24, result, LSB);
10288       movLeft2Result(left, MSB32, result, MSB16);
10289     }
10290     pic16_addSign(result, MSB24, sign);
10291   }
10292   else if(shCount >= 8){
10293     shCount -= 8;
10294     if(shCount == 1)
10295       shiftRLong(left, MSB16, result, sign);
10296     else if(shCount == 0){
10297       movLeft2Result(left, MSB16, result, LSB);
10298       movLeft2Result(left, MSB24, result, MSB16);
10299       movLeft2Result(left, MSB32, result, MSB24);
10300       pic16_addSign(result, MSB32, sign);
10301     }
10302     else{ //shcount >= 2
10303       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10304       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10305       /* the last shift is signed */
10306       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10307       pic16_addSign(result, MSB32, sign);
10308     }
10309   }
10310   else{   /* 1 <= shCount <= 7 */
10311     if(shCount <= 2){
10312       shiftRLong(left, LSB, result, sign);
10313       if(shCount == 2)
10314         shiftRLong(result, LSB, result, sign);
10315     }
10316     else{
10317       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10318       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10319       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10320     }
10321   }
10322 }
10323
10324 /*-----------------------------------------------------------------*/
10325 /* genRightShiftLiteral - right shifting by known count            */
10326 /*-----------------------------------------------------------------*/
10327 static void genRightShiftLiteral (operand *left,
10328                                   operand *right,
10329                                   operand *result,
10330                                   iCode *ic,
10331                                   int sign)
10332 {    
10333   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10334   int lsize,res_size;
10335
10336   pic16_freeAsmop(right,NULL,ic,TRUE);
10337
10338   pic16_aopOp(left,ic,FALSE);
10339   pic16_aopOp(result,ic,FALSE);
10340
10341   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10342
10343 #if VIEW_SIZE
10344   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10345                  AOP_SIZE(left));
10346 #endif
10347
10348   lsize = pic16_getDataSize(left);
10349   res_size = pic16_getDataSize(result);
10350   /* test the LEFT size !!! */
10351
10352   /* I suppose that the left size >= result size */
10353   if(shCount == 0){
10354     while(res_size--)
10355       movLeft2Result(left, lsize, result, res_size);
10356   }
10357
10358   else if(shCount >= (lsize * 8)){
10359
10360     if(res_size == 1) {
10361       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10362       if(sign) {
10363         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10364         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10365       }
10366     } else {
10367
10368       if(sign) {
10369         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10370         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10371         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10372         while(res_size--)
10373           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10374
10375       } else {
10376
10377         while(res_size--)
10378           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10379       }
10380     }
10381   } else {
10382
10383     switch (res_size) {
10384     case 1:
10385       genrshOne (result,left,shCount,sign);
10386       break;
10387
10388     case 2:
10389       genrshTwo (result,left,shCount,sign);
10390       break;
10391
10392     case 4:
10393       genrshFour (result,left,shCount,sign);
10394       break;
10395     default :
10396       break;
10397     }
10398
10399   }
10400
10401   pic16_freeAsmop(left,NULL,ic,TRUE);
10402   pic16_freeAsmop(result,NULL,ic,TRUE);
10403 }
10404
10405 #if !(USE_GENERIC_SIGNED_SHIFT)
10406 /*-----------------------------------------------------------------*/
10407 /* genSignedRightShift - right shift of signed number              */
10408 /*-----------------------------------------------------------------*/
10409 static void genSignedRightShift (iCode *ic)
10410 {
10411   operand *right, *left, *result;
10412   int size, offset;
10413   //  char *l;
10414   symbol *tlbl, *tlbl1 ;
10415   pCodeOp *pctemp;
10416
10417   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10418
10419   /* we do it the hard way put the shift count in b
10420      and loop thru preserving the sign */
10421   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10422
10423   right = IC_RIGHT(ic);
10424   left  = IC_LEFT(ic);
10425   result = IC_RESULT(ic);
10426
10427   pic16_aopOp(right,ic,FALSE);  
10428   pic16_aopOp(left,ic,FALSE);
10429   pic16_aopOp(result,ic,FALSE);
10430
10431
10432   if ( AOP_TYPE(right) == AOP_LIT) {
10433     genRightShiftLiteral (left,right,result,ic,1);
10434     return ;
10435   }
10436   /* shift count is unknown then we have to form 
10437      a loop get the loop count in B : Note: we take
10438      only the lower order byte since shifting
10439      more that 32 bits make no sense anyway, ( the
10440      largest size of an object can be only 32 bits ) */  
10441
10442   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10443   //pic16_emitcode("inc","b");
10444   //pic16_freeAsmop (right,NULL,ic,TRUE);
10445   //pic16_aopOp(left,ic,FALSE);
10446   //pic16_aopOp(result,ic,FALSE);
10447
10448   /* now move the left to the result if they are not the
10449      same */
10450   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10451       AOP_SIZE(result) > 1) {
10452
10453     size = AOP_SIZE(result);
10454     offset=0;
10455     while (size--) { 
10456       /*
10457         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10458         if (*l == '@' && IS_AOP_PREG(result)) {
10459
10460         pic16_emitcode("mov","a,%s",l);
10461         pic16_aopPut(AOP(result),"a",offset);
10462         } else
10463         pic16_aopPut(AOP(result),l,offset);
10464       */
10465       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10466       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10467
10468       offset++;
10469     }
10470   }
10471
10472   /* mov the highest order bit to OVR */    
10473   tlbl = newiTempLabel(NULL);
10474   tlbl1= newiTempLabel(NULL);
10475
10476   size = AOP_SIZE(result);
10477   offset = size - 1;
10478
10479   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10480
10481   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10482
10483   /* offset should be 0, 1 or 3 */
10484   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10485   emitSKPNZ;
10486   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10487
10488   pic16_emitpcode(POC_MOVWF, pctemp);
10489
10490
10491   pic16_emitpLabel(tlbl->key);
10492
10493   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10494   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10495
10496   while(--size) {
10497     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10498   }
10499
10500   pic16_emitpcode(POC_DECFSZ,  pctemp);
10501   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10502   pic16_emitpLabel(tlbl1->key);
10503
10504   pic16_popReleaseTempReg(pctemp,1);
10505 #if 0
10506   size = AOP_SIZE(result);
10507   offset = size - 1;
10508   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10509   pic16_emitcode("rlc","a");
10510   pic16_emitcode("mov","ov,c");
10511   /* if it is only one byte then */
10512   if (size == 1) {
10513     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10514     MOVA(l);
10515     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10516     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10517     pic16_emitcode("mov","c,ov");
10518     pic16_emitcode("rrc","a");
10519     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10520     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10521     pic16_aopPut(AOP(result),"a",0);
10522     goto release ;
10523   }
10524
10525   reAdjustPreg(AOP(result));
10526   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10527   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10528   pic16_emitcode("mov","c,ov");
10529   while (size--) {
10530     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10531     MOVA(l);
10532     pic16_emitcode("rrc","a");         
10533     pic16_aopPut(AOP(result),"a",offset--);
10534   }
10535   reAdjustPreg(AOP(result));
10536   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10537   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10538
10539  release:
10540 #endif
10541
10542   pic16_freeAsmop(left,NULL,ic,TRUE);
10543   pic16_freeAsmop(result,NULL,ic,TRUE);
10544   pic16_freeAsmop(right,NULL,ic,TRUE);
10545 }
10546 #endif
10547
10548 #if !(USE_GENERIC_SIGNED_SHIFT)
10549 #warning This implementation of genRightShift() is incomplete!
10550 /*-----------------------------------------------------------------*/
10551 /* genRightShift - generate code for right shifting                */
10552 /*-----------------------------------------------------------------*/
10553 static void genRightShift (iCode *ic)
10554 {
10555     operand *right, *left, *result;
10556     sym_link *letype ;
10557     int size, offset;
10558     char *l;
10559     symbol *tlbl, *tlbl1 ;
10560
10561     /* if signed then we do it the hard way preserve the
10562     sign bit moving it inwards */
10563     letype = getSpec(operandType(IC_LEFT(ic)));
10564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10565
10566     if (!SPEC_USIGN(letype)) {
10567         genSignedRightShift (ic);
10568         return ;
10569     }
10570
10571     /* signed & unsigned types are treated the same : i.e. the
10572     signed is NOT propagated inwards : quoting from the
10573     ANSI - standard : "for E1 >> E2, is equivalent to division
10574     by 2**E2 if unsigned or if it has a non-negative value,
10575     otherwise the result is implementation defined ", MY definition
10576     is that the sign does not get propagated */
10577
10578     right = IC_RIGHT(ic);
10579     left  = IC_LEFT(ic);
10580     result = IC_RESULT(ic);
10581
10582     pic16_aopOp(right,ic,FALSE);
10583
10584     /* if the shift count is known then do it 
10585     as efficiently as possible */
10586     if (AOP_TYPE(right) == AOP_LIT) {
10587         genRightShiftLiteral (left,right,result,ic, 0);
10588         return ;
10589     }
10590
10591     /* shift count is unknown then we have to form 
10592     a loop get the loop count in B : Note: we take
10593     only the lower order byte since shifting
10594     more that 32 bits make no sense anyway, ( the
10595     largest size of an object can be only 32 bits ) */  
10596
10597     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10598     pic16_emitcode("inc","b");
10599     pic16_aopOp(left,ic,FALSE);
10600     pic16_aopOp(result,ic,FALSE);
10601
10602     /* now move the left to the result if they are not the
10603     same */
10604     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10605         AOP_SIZE(result) > 1) {
10606
10607         size = AOP_SIZE(result);
10608         offset=0;
10609         while (size--) {
10610             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10611             if (*l == '@' && IS_AOP_PREG(result)) {
10612
10613                 pic16_emitcode("mov","a,%s",l);
10614                 pic16_aopPut(AOP(result),"a",offset);
10615             } else
10616                 pic16_aopPut(AOP(result),l,offset);
10617             offset++;
10618         }
10619     }
10620
10621     tlbl = newiTempLabel(NULL);
10622     tlbl1= newiTempLabel(NULL);
10623     size = AOP_SIZE(result);
10624     offset = size - 1;
10625
10626     /* if it is only one byte then */
10627     if (size == 1) {
10628
10629       tlbl = newiTempLabel(NULL);
10630       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10631         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10632         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10633       }
10634
10635       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10636       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10637       pic16_emitpLabel(tlbl->key);
10638       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10639       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10640       emitSKPC;
10641       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10642
10643       goto release ;
10644     }
10645
10646     reAdjustPreg(AOP(result));
10647     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10648     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10649     CLRC;
10650     while (size--) {
10651         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10652         MOVA(l);
10653         pic16_emitcode("rrc","a");         
10654         pic16_aopPut(AOP(result),"a",offset--);
10655     }
10656     reAdjustPreg(AOP(result));
10657
10658     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10659     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10660
10661 release:
10662     pic16_freeAsmop(left,NULL,ic,TRUE);
10663     pic16_freeAsmop (right,NULL,ic,TRUE);
10664     pic16_freeAsmop(result,NULL,ic,TRUE);
10665 }
10666 #endif
10667
10668 #if (USE_GENERIC_SIGNED_SHIFT)
10669 /*-----------------------------------------------------------------*/
10670 /* genGenericShift - generates code for left or right shifting     */
10671 /*-----------------------------------------------------------------*/
10672 static void genGenericShift (iCode *ic, int isShiftLeft) {
10673   operand *left,*right, *result;
10674   int offset;
10675   int sign, signedCount;
10676   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10677   PIC_OPCODE pos_shift, neg_shift;
10678
10679   FENTRY;
10680
10681   right = IC_RIGHT(ic);
10682   left  = IC_LEFT(ic);
10683   result = IC_RESULT(ic);
10684
10685   pic16_aopOp(right,ic,FALSE);
10686   pic16_aopOp(left,ic,FALSE);
10687   pic16_aopOp(result,ic,FALSE);
10688
10689   sign = !SPEC_USIGN(operandType (left));
10690   signedCount = !SPEC_USIGN(operandType (right));
10691
10692   /* if the shift count is known then do it 
10693      as efficiently as possible */
10694   if (AOP_TYPE(right) == AOP_LIT) {
10695     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10696     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10697     // we should modify right->aopu.aop_lit here!
10698     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10699     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10700     if (isShiftLeft)
10701       pic16_genLeftShiftLiteral (left,right,result,ic);
10702     else
10703       genRightShiftLiteral (left,right,result,ic, sign);
10704
10705     goto release;
10706   } // if (right is literal)
10707
10708   /* shift count is unknown then we have to form a loop.
10709    * Note: we take only the lower order byte since shifting
10710    * more than 32 bits make no sense anyway, ( the
10711    * largest size of an object can be only 32 bits )
10712    * Note: we perform arithmetic shifts if the left operand is
10713    * signed and we do an (effective) right shift, i. e. we
10714    * shift in the sign bit from the left. */
10715    
10716   label_complete = newiTempLabel ( NULL );
10717   label_loop_pos = newiTempLabel ( NULL );
10718   label_loop_neg = NULL;
10719   label_negative = NULL;
10720   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10721   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10722
10723   if (signedCount) {
10724     // additional labels needed
10725     label_loop_neg = newiTempLabel ( NULL );
10726     label_negative = newiTempLabel ( NULL );
10727   } // if
10728
10729   // copy source to result -- this will effectively truncate the left operand to the size of result!
10730   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10731   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10732   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10733     mov2f (AOP(result),AOP(left), offset);
10734   } // for
10735
10736   // if result is longer than left, fill with zeros (or sign)
10737   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10738     if (sign && AOP_SIZE(left) > 0) {
10739       // shift signed operand -- fill with sign
10740       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10741       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10742       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10743       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10744         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10745       } // for
10746     } else {
10747       // shift unsigned operand -- fill result with zeros
10748       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10749         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10750       } // for
10751     }
10752   } // if (size mismatch)
10753
10754   pic16_mov2w (AOP(right), 0);
10755   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10756   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10757   
10758 #if 0
10759   // perform a shift by one (shift count is positive)
10760   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10761   // 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])
10762   pic16_emitpLabel (label_loop_pos->key);
10763   emitCLRC;
10764   if (sign && (pos_shift == POC_RRCF)) {
10765     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10766     emitSETC;
10767   } // if
10768   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10769   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10770   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10771 #else
10772   // perform a shift by one (shift count is positive)
10773   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10774   // 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])
10775   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10776   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10777   emitCLRC;
10778   pic16_emitpLabel (label_loop_pos->key);
10779   if (sign && (pos_shift == POC_RRCF)) {
10780     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10781     emitSETC;
10782   } // if
10783   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10784   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10785   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10786   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10787 #endif
10788
10789   if (signedCount) {
10790     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10791
10792     pic16_emitpLabel (label_negative->key);
10793     // perform a shift by -1 (shift count is negative)
10794     // 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)
10795     emitCLRC;
10796     pic16_emitpLabel (label_loop_neg->key);
10797     if (sign && (neg_shift == POC_RRCF)) {
10798       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10799       emitSETC;
10800     } // if
10801     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10802     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10803     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10804     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10805   } // if (signedCount)
10806
10807   pic16_emitpLabel (label_complete->key);
10808
10809 release:
10810   pic16_freeAsmop (right,NULL,ic,TRUE);
10811   pic16_freeAsmop(left,NULL,ic,TRUE);
10812   pic16_freeAsmop(result,NULL,ic,TRUE);
10813 }
10814
10815 static void genLeftShift (iCode *ic) {
10816   genGenericShift (ic, 1);
10817 }
10818
10819 static void genRightShift (iCode *ic) {
10820   genGenericShift (ic, 0);
10821 }
10822 #endif
10823
10824
10825 void pic16_loadFSR0(operand *op)
10826 {
10827         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10828 }
10829
10830 /*-----------------------------------------------------------------*/
10831 /* genUnpackBits - generates code for unpacking bits               */
10832 /*-----------------------------------------------------------------*/
10833 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10834 {    
10835   int shCnt ;
10836   int rlen = 0 ;
10837   sym_link *etype, *letype;
10838   int blen=0, bstr=0;
10839   int lbstr;
10840   int offset = 0 ;
10841
10842     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10843     etype = getSpec(operandType(result));
10844     letype = getSpec(operandType(left));
10845     
10846 //    if(IS_BITFIELD(etype)) {
10847       blen = SPEC_BLEN(etype);
10848       bstr = SPEC_BSTR(etype);
10849 //    }
10850
10851     lbstr = SPEC_BSTR( letype );
10852
10853 #if 1
10854     if((blen == 1) && (bstr < 8)) {
10855       /* it is a single bit, so use the appropriate bit instructions */
10856       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10857
10858       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10859       
10860       if((ptype == POINTER) && (result)) {
10861         /* workaround to reduce the extra lfsr instruction */
10862         pic16_emitpcode(POC_BTFSC,
10863               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10864       } else {
10865         pic16_emitpcode(POC_BTFSC,
10866               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10867       }
10868         
10869       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10870
10871       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10872       return;
10873     }
10874
10875 #endif
10876
10877         /* the following call to pic16_loadFSR0 is temporary until
10878          * optimization to handle single bit assignments is added
10879          * to the function. Until then use the old safe way! -- VR */
10880         pic16_loadFSR0( left );
10881  
10882         /* read the first byte  */
10883         switch (ptype) {
10884                 case POINTER:
10885                 case IPOINTER:
10886                 case PPOINTER:
10887                 case FPOINTER:
10888                 case GPOINTER:
10889                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10890                         break;
10891                 case CPOINTER:
10892                         pic16_emitcode("clr","a");
10893                         pic16_emitcode("movc","a","@a+dptr");
10894                         break;
10895         }
10896         
10897
10898         /* if we have bitdisplacement then it fits   */
10899         /* into this byte completely or if length is */
10900         /* less than a byte                          */
10901         if ((shCnt = SPEC_BSTR(etype)) || 
10902                 (SPEC_BLEN(etype) <= 8))  {
10903
10904                 /* shift right acc */
10905                 AccRsh(shCnt, 0);
10906
10907                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10908                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10909
10910 /* VR -- normally I would use the following, but since we use the hack,
10911  * to avoid the masking from AccRsh, why not mask it right now? */
10912
10913 /*
10914                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10915 */
10916
10917                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10918           return ;
10919         }
10920
10921
10922
10923         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10924         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10925         exit(-1);
10926
10927     /* bit field did not fit in a byte  */
10928     rlen = SPEC_BLEN(etype) - 8;
10929     pic16_aopPut(AOP(result),"a",offset++);
10930
10931     while (1)  {
10932
10933         switch (ptype) {
10934         case POINTER:
10935         case IPOINTER:
10936             pic16_emitcode("inc","%s",rname);
10937             pic16_emitcode("mov","a,@%s",rname);
10938             break;
10939             
10940         case PPOINTER:
10941             pic16_emitcode("inc","%s",rname);
10942             pic16_emitcode("movx","a,@%s",rname);
10943             break;
10944
10945         case FPOINTER:
10946             pic16_emitcode("inc","dptr");
10947             pic16_emitcode("movx","a,@dptr");
10948             break;
10949             
10950         case CPOINTER:
10951             pic16_emitcode("clr","a");
10952             pic16_emitcode("inc","dptr");
10953             pic16_emitcode("movc","a","@a+dptr");
10954             break;
10955             
10956         case GPOINTER:
10957             pic16_emitcode("inc","dptr");
10958             pic16_emitcode("lcall","__gptrget");
10959             break;
10960         }
10961
10962         rlen -= 8;            
10963         /* if we are done */
10964         if ( rlen <= 0 )
10965             break ;
10966         
10967         pic16_aopPut(AOP(result),"a",offset++);
10968                               
10969     }
10970     
10971     if (rlen) {
10972         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10973         pic16_aopPut(AOP(result),"a",offset);          
10974     }
10975     
10976     return ;
10977 }
10978
10979
10980 static void genDataPointerGet(operand *left,
10981                               operand *result,
10982                               iCode *ic)
10983 {
10984   int size, offset = 0, leoffset=0 ;
10985
10986         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10987         pic16_aopOp(result, ic, FALSE);
10988
10989         size = AOP_SIZE(result);
10990 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10991
10992
10993 #if 0
10994         /* The following tests may save a redudant movff instruction when
10995          * accessing unions */
10996          
10997         /* if they are the same */
10998         if (operandsEqu (left, result)) {
10999                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11000                 goto release;
11001         }
11002 #endif
11003
11004 #if 0
11005         /* if they are the same registers */
11006         if (pic16_sameRegs(AOP(left),AOP(result))) {
11007                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11008                 goto release;
11009         }
11010 #endif
11011
11012 #if 1
11013         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11014                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11015                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11016                 goto release;
11017         }
11018 #endif
11019
11020
11021 #if 0
11022         if ( AOP_TYPE(left) == AOP_PCODE) {
11023                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
11024                                 AOP(left)->aopu.pcop->name,
11025                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
11026                                 PCOR(AOP(left)->aopu.pcop)->instance:
11027                                 PCOI(AOP(left)->aopu.pcop)->offset);
11028         }
11029 #endif
11030
11031         if(AOP(left)->aopu.pcop->type == PO_DIR)
11032                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11033
11034         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11035
11036         while (size--) {
11037                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11038                 
11039                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11040                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11041                         pic16_mov2w(AOP(left), offset); // patch 8
11042                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11043                 } else {
11044                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11045                                 pic16_popGet(AOP(left), offset), //patch 8
11046                                 pic16_popGet(AOP(result), offset)));
11047                 }
11048
11049                 offset++;
11050                 leoffset++;
11051         }
11052
11053 release:
11054     pic16_freeAsmop(result,NULL,ic,TRUE);
11055 }
11056
11057
11058
11059 /*-----------------------------------------------------------------*/
11060 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11061 /*-----------------------------------------------------------------*/
11062 static void genNearPointerGet (operand *left, 
11063                                operand *result, 
11064                                iCode *ic)
11065 {
11066   asmop *aop = NULL;
11067   //regs *preg = NULL ;
11068   sym_link *rtype, *retype;
11069   sym_link *ltype = operandType(left);    
11070
11071     FENTRY;
11072     
11073     rtype = operandType(result);
11074     retype= getSpec(rtype);
11075     
11076     pic16_aopOp(left,ic,FALSE);
11077
11078 //    pic16_DumpOp("(left)",left);
11079 //    pic16_DumpOp("(result)",result);
11080
11081     /* if left is rematerialisable and
11082      * result is not bit variable type and
11083      * the left is pointer to data space i.e
11084      * lower 128 bytes of space */
11085     
11086     if (AOP_TYPE(left) == AOP_PCODE
11087       && !IS_BITFIELD(retype)
11088       && DCL_TYPE(ltype) == POINTER) {
11089
11090         genDataPointerGet (left,result,ic);
11091         pic16_freeAsmop(left, NULL, ic, TRUE);
11092         return ;
11093     }
11094     
11095     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11096     pic16_aopOp (result,ic,FALSE);
11097     
11098     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11099
11100 #if 1
11101     if(IS_BITFIELD( retype )
11102       && (SPEC_BLEN(operandType(result))==1)
11103     ) {
11104       iCode *nextic;
11105       pCodeOp *jop;
11106       int bitstrt, bytestrt;
11107
11108         /* if this is bitfield of size 1, see if we are checking the value
11109          * of a single bit in an if-statement,
11110          * if yes, then don't generate usual code, but execute the
11111          * genIfx directly -- VR */
11112
11113         nextic = ic->next;
11114
11115         /* CHECK: if next iCode is IFX
11116          * and current result operand is nextic's conditional operand
11117          * and current result operand live ranges ends at nextic's key number
11118          */
11119         if((nextic->op == IFX)
11120           && (result == IC_COND(nextic))
11121           && (OP_LIVETO(result) == nextic->seq)
11122           ) {
11123             /* everything is ok then */
11124             /* find a way to optimize the genIfx iCode */
11125
11126             bytestrt = SPEC_BSTR(operandType(result))/8;
11127             bitstrt = SPEC_BSTR(operandType(result))%8;
11128             
11129             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11130
11131             genIfxpCOpJump(nextic, jop);
11132             
11133             pic16_freeAsmop(left, NULL, ic, TRUE);
11134             pic16_freeAsmop(result, NULL, ic, TRUE);
11135             return;
11136         }
11137     }
11138 #endif
11139
11140
11141     /* if the value is already in a pointer register
11142      * then don't need anything more */
11143     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11144       /* otherwise get a free pointer register */
11145       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11146                 
11147       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11148       /* bitfields will be handled by genUnpackBits */
11149       if(!IS_BITFIELD(retype)) {
11150
11151         if(is_LitAOp( AOP(left) )) {
11152           pic16_loadFSR0( left );
11153         } else {
11154             // set up FSR0 with address from left
11155             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11156             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11157         }
11158       }
11159     }
11160
11161     /* if bitfield then unpack the bits */
11162     if (IS_BITFIELD(retype)) 
11163       genUnpackBits (result, left, NULL, POINTER);
11164     else {
11165       /* we have can just get the values */
11166       int size = AOP_SIZE(result);
11167       int offset = 0;   
11168         
11169       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11170
11171       /* fsr0 is loaded already -- VR */
11172 //      pic16_loadFSR0( left );
11173
11174 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11175 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11176       while(size--) {
11177         if(size) {
11178           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11179                 pic16_popGet(AOP(result), offset++)));
11180         } else {
11181           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11182                 pic16_popGet(AOP(result), offset++)));
11183         }
11184       }
11185 #if 0
11186 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11187 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11188       if(size)
11189         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11190 #endif
11191 /*
11192         while (size--) {
11193             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11194
11195                 pic16_emitcode("mov","a,@%s",rname);
11196                 pic16_aopPut(AOP(result),"a",offset);
11197             } else {
11198                 sprintf(buffer,"@%s",rname);
11199                 pic16_aopPut(AOP(result),buffer,offset);
11200             }
11201             offset++ ;
11202             if (size)
11203                 pic16_emitcode("inc","%s",rname);
11204         }
11205 */
11206     }
11207
11208     /* now some housekeeping stuff */
11209     if (aop) {
11210       /* we had to allocate for this iCode */
11211       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11212       pic16_freeAsmop(NULL,aop,ic,TRUE);
11213     } else { 
11214       /* we did not allocate which means left
11215        * already in a pointer register, then
11216        * if size > 0 && this could be used again
11217        * we have to point it back to where it 
11218        * belongs */
11219       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11220       if (AOP_SIZE(result) > 1
11221         && !OP_SYMBOL(left)->remat
11222         && ( OP_SYMBOL(left)->liveTo > ic->seq
11223             || ic->depth )) {
11224 //        int size = AOP_SIZE(result) - 1;
11225 //        while (size--)
11226 //          pic16_emitcode("dec","%s",rname);
11227         }
11228     }
11229
11230     /* done */
11231     pic16_freeAsmop(left,NULL,ic,TRUE);
11232     pic16_freeAsmop(result,NULL,ic,TRUE);
11233 }
11234
11235 /*-----------------------------------------------------------------*/
11236 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11237 /*-----------------------------------------------------------------*/
11238 static void genPagedPointerGet (operand *left, 
11239                                operand *result, 
11240                                iCode *ic)
11241 {
11242     asmop *aop = NULL;
11243     regs *preg = NULL ;
11244     char *rname ;
11245     sym_link *rtype, *retype;    
11246
11247     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11248
11249     rtype = operandType(result);
11250     retype= getSpec(rtype);
11251     
11252     pic16_aopOp(left,ic,FALSE);
11253
11254   /* if the value is already in a pointer register
11255        then don't need anything more */
11256     if (!AOP_INPREG(AOP(left))) {
11257         /* otherwise get a free pointer register */
11258         aop = newAsmop(0);
11259         preg = getFreePtr(ic,&aop,FALSE);
11260         pic16_emitcode("mov","%s,%s",
11261                 preg->name,
11262                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11263         rname = preg->name ;
11264     } else
11265         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11266     
11267     pic16_freeAsmop(left,NULL,ic,TRUE);
11268     pic16_aopOp (result,ic,FALSE);
11269
11270     /* if bitfield then unpack the bits */
11271     if (IS_BITFIELD(retype)) 
11272         genUnpackBits (result,left,rname,PPOINTER);
11273     else {
11274         /* we have can just get the values */
11275         int size = AOP_SIZE(result);
11276         int offset = 0 ;        
11277         
11278         while (size--) {
11279             
11280             pic16_emitcode("movx","a,@%s",rname);
11281             pic16_aopPut(AOP(result),"a",offset);
11282             
11283             offset++ ;
11284             
11285             if (size)
11286                 pic16_emitcode("inc","%s",rname);
11287         }
11288     }
11289
11290     /* now some housekeeping stuff */
11291     if (aop) {
11292         /* we had to allocate for this iCode */
11293         pic16_freeAsmop(NULL,aop,ic,TRUE);
11294     } else { 
11295         /* we did not allocate which means left
11296            already in a pointer register, then
11297            if size > 0 && this could be used again
11298            we have to point it back to where it 
11299            belongs */
11300         if (AOP_SIZE(result) > 1 &&
11301             !OP_SYMBOL(left)->remat &&
11302             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11303               ic->depth )) {
11304             int size = AOP_SIZE(result) - 1;
11305             while (size--)
11306                 pic16_emitcode("dec","%s",rname);
11307         }
11308     }
11309
11310     /* done */
11311     pic16_freeAsmop(result,NULL,ic,TRUE);
11312     
11313         
11314 }
11315
11316 /*-----------------------------------------------------------------*/
11317 /* genFarPointerGet - gget value from far space                    */
11318 /*-----------------------------------------------------------------*/
11319 static void genFarPointerGet (operand *left,
11320                               operand *result, iCode *ic)
11321 {
11322     int size, offset ;
11323     sym_link *retype = getSpec(operandType(result));
11324
11325     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11326
11327     pic16_aopOp(left,ic,FALSE);
11328
11329     /* if the operand is already in dptr 
11330     then we do nothing else we move the value to dptr */
11331     if (AOP_TYPE(left) != AOP_STR) {
11332         /* if this is remateriazable */
11333         if (AOP_TYPE(left) == AOP_IMMD)
11334             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11335         else { /* we need to get it byte by byte */
11336             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11337             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11338             if (options.model == MODEL_FLAT24)
11339             {
11340                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11341             }
11342         }
11343     }
11344     /* so dptr know contains the address */
11345     pic16_freeAsmop(left,NULL,ic,TRUE);
11346     pic16_aopOp(result,ic,FALSE);
11347
11348     /* if bit then unpack */
11349     if (IS_BITFIELD(retype)) 
11350         genUnpackBits(result,left,"dptr",FPOINTER);
11351     else {
11352         size = AOP_SIZE(result);
11353         offset = 0 ;
11354
11355         while (size--) {
11356             pic16_emitcode("movx","a,@dptr");
11357             pic16_aopPut(AOP(result),"a",offset++);
11358             if (size)
11359                 pic16_emitcode("inc","dptr");
11360         }
11361     }
11362
11363     pic16_freeAsmop(result,NULL,ic,TRUE);
11364 }
11365
11366 #if 0
11367 /*-----------------------------------------------------------------*/
11368 /* genCodePointerGet - get value from code space                  */
11369 /*-----------------------------------------------------------------*/
11370 static void genCodePointerGet (operand *left,
11371                                 operand *result, iCode *ic)
11372 {
11373     int size, offset ;
11374     sym_link *retype = getSpec(operandType(result));
11375
11376     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11377
11378     pic16_aopOp(left,ic,FALSE);
11379
11380     /* if the operand is already in dptr 
11381     then we do nothing else we move the value to dptr */
11382     if (AOP_TYPE(left) != AOP_STR) {
11383         /* if this is remateriazable */
11384         if (AOP_TYPE(left) == AOP_IMMD)
11385             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11386         else { /* we need to get it byte by byte */
11387             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11388             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11389             if (options.model == MODEL_FLAT24)
11390             {
11391                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11392             }
11393         }
11394     }
11395     /* so dptr know contains the address */
11396     pic16_freeAsmop(left,NULL,ic,TRUE);
11397     pic16_aopOp(result,ic,FALSE);
11398
11399     /* if bit then unpack */
11400     if (IS_BITFIELD(retype)) 
11401         genUnpackBits(result,left,"dptr",CPOINTER);
11402     else {
11403         size = AOP_SIZE(result);
11404         offset = 0 ;
11405
11406         while (size--) {
11407             pic16_emitcode("clr","a");
11408             pic16_emitcode("movc","a,@a+dptr");
11409             pic16_aopPut(AOP(result),"a",offset++);
11410             if (size)
11411                 pic16_emitcode("inc","dptr");
11412         }
11413     }
11414
11415     pic16_freeAsmop(result,NULL,ic,TRUE);
11416 }
11417 #endif
11418
11419 #if 0
11420 /*-----------------------------------------------------------------*/
11421 /* genGenPointerGet - gget value from generic pointer space        */
11422 /*-----------------------------------------------------------------*/
11423 static void genGenPointerGet (operand *left,
11424                               operand *result, iCode *ic)
11425 {
11426   int size, offset, lit;
11427   sym_link *retype = getSpec(operandType(result));
11428
11429         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11430         pic16_aopOp(left,ic,FALSE);
11431         pic16_aopOp(result,ic,FALSE);
11432         size = AOP_SIZE(result);
11433
11434         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11435
11436         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11437
11438                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11439                 // load FSR0 from immediate
11440                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11441
11442 //              pic16_loadFSR0( left );
11443
11444                 offset = 0;
11445                 while(size--) {
11446                         if(size) {
11447                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11448                         } else {
11449                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11450                         }
11451                         offset++;
11452                 }
11453                 goto release;
11454
11455         }
11456         else { /* we need to get it byte by byte */
11457                 // set up FSR0 with address from left
11458                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11459                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11460
11461                 offset = 0 ;
11462
11463                 while(size--) {
11464                         if(size) {
11465                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11466                         } else {
11467                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11468                         }
11469                         offset++;
11470                 }
11471                 goto release;
11472         }
11473
11474   /* if bit then unpack */
11475         if (IS_BITFIELD(retype)) 
11476                 genUnpackBits(result,left,"BAD",GPOINTER);
11477
11478         release:
11479         pic16_freeAsmop(left,NULL,ic,TRUE);
11480         pic16_freeAsmop(result,NULL,ic,TRUE);
11481
11482 }
11483 #endif
11484
11485
11486 /*-----------------------------------------------------------------*/
11487 /* genGenPointerGet - gget value from generic pointer space        */
11488 /*-----------------------------------------------------------------*/
11489 static void genGenPointerGet (operand *left,
11490                               operand *result, iCode *ic)
11491 {
11492   int size, offset, lit;
11493   sym_link *retype = getSpec(operandType(result));
11494   char fgptrget[32];
11495
11496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11497     pic16_aopOp(left,ic,FALSE);
11498     pic16_aopOp(result,ic,FALSE);
11499     size = AOP_SIZE(result);
11500
11501     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11502
11503     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11504
11505       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11506       // load FSR0 from immediate
11507       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11508
11509       werror(W_POSSBUG2, __FILE__, __LINE__);
11510
11511       offset = 0;
11512       while(size--) {
11513         if(size) {
11514           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11515         } else {
11516           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11517         }
11518         offset++;
11519       }
11520
11521       goto release;
11522
11523     } else { /* we need to get it byte by byte */
11524
11525       /* set up WREG:PRODL:FSR0L with address from left */
11526       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11527       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11528       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11529       
11530       switch( size ) {
11531         case 1: strcpy(fgptrget, "__gptrget1"); break;
11532         case 2: strcpy(fgptrget, "__gptrget2"); break;
11533         case 3: strcpy(fgptrget, "__gptrget3"); break;
11534         case 4: strcpy(fgptrget, "__gptrget4"); break;
11535         default:
11536           werror(W_POSSBUG2, __FILE__, __LINE__);
11537           abort();
11538       }
11539       
11540       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11541       
11542       assignResultValue(result, 1);
11543       
11544       {
11545         symbol *sym;
11546
11547           sym = newSymbol( fgptrget, 0 );
11548           strcpy(sym->rname, fgptrget);
11549           checkAddSym(&externs, sym);
11550
11551 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11552       }
11553               
11554       goto release;
11555     }
11556
11557   /* if bit then unpack */
11558     if (IS_BITFIELD(retype)) 
11559       genUnpackBits(result,left,"BAD",GPOINTER);
11560
11561 release:
11562   pic16_freeAsmop(left,NULL,ic,TRUE);
11563   pic16_freeAsmop(result,NULL,ic,TRUE);
11564 }
11565
11566 /*-----------------------------------------------------------------*/
11567 /* genConstPointerGet - get value from const generic pointer space */
11568 /*-----------------------------------------------------------------*/
11569 static void genConstPointerGet (operand *left,
11570                                 operand *result, iCode *ic)
11571 {
11572   //sym_link *retype = getSpec(operandType(result));
11573   // symbol *albl = newiTempLabel(NULL);        // patch 15
11574   // symbol *blbl = newiTempLabel(NULL);        //
11575   // PIC_OPCODE poc;                            // patch 15
11576   int size;
11577   int offset = 0;
11578
11579   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11580   pic16_aopOp(left,ic,FALSE);
11581   pic16_aopOp(result,ic,TRUE);
11582   size = AOP_SIZE(result);
11583
11584   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11585
11586   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11587
11588   // set up table pointer
11589   if( (AOP_TYPE(left) == AOP_PCODE) 
11590       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11591           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11592     {
11593       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11594       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11595       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11596       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11597       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11598       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11599   } else {
11600     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11601     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11602     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11603   }
11604
11605   while(size--) {
11606     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11607     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11608     offset++;
11609   }
11610     
11611   pic16_freeAsmop(left,NULL,ic,TRUE);
11612   pic16_freeAsmop(result,NULL,ic,TRUE);
11613 }
11614
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genPointerGet - generate code for pointer get                   */
11618 /*-----------------------------------------------------------------*/
11619 static void genPointerGet (iCode *ic)
11620 {
11621   operand *left, *result ;
11622   sym_link *type, *etype;
11623   int p_type;
11624
11625     FENTRY;
11626     
11627     left = IC_LEFT(ic);
11628     result = IC_RESULT(ic) ;
11629
11630     /* depending on the type of pointer we need to
11631     move it to the correct pointer register */
11632     type = operandType(left);
11633     etype = getSpec(type);
11634
11635 #if 0
11636     if (IS_PTR_CONST(type))
11637 #else
11638     if (IS_CODEPTR(type))
11639 #endif
11640       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11641
11642     /* if left is of type of pointer then it is simple */
11643     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11644       p_type = DCL_TYPE(type);
11645     else {
11646       /* we have to go by the storage class */
11647       p_type = PTR_TYPE(SPEC_OCLS(etype));
11648
11649       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11650
11651       if (SPEC_OCLS(etype)->codesp ) {
11652         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11653         //p_type = CPOINTER ;   
11654       } else
11655       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11656         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11657         /*p_type = FPOINTER ;*/ 
11658       } else
11659       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11660         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11661         /* p_type = PPOINTER; */
11662       } else
11663       if (SPEC_OCLS(etype) == idata ) {
11664         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11665         /* p_type = IPOINTER; */
11666       } else {
11667         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11668         /* p_type = POINTER ; */
11669       }
11670     }
11671
11672     /* now that we have the pointer type we assign
11673     the pointer values */
11674     switch (p_type) {
11675       case POINTER:     
11676       case IPOINTER:
11677         genNearPointerGet (left,result,ic);
11678         break;
11679
11680       case PPOINTER:
11681         genPagedPointerGet(left,result,ic);
11682         break;
11683
11684       case FPOINTER:
11685         genFarPointerGet (left,result,ic);
11686         break;
11687
11688       case CPOINTER:
11689         genConstPointerGet (left,result,ic);
11690         //pic16_emitcodePointerGet (left,result,ic);
11691         break;
11692
11693       case GPOINTER:
11694 #if 0
11695       if (IS_PTR_CONST(type))
11696         genConstPointerGet (left,result,ic);
11697       else
11698 #endif
11699         genGenPointerGet (left,result,ic);
11700       break;
11701
11702     default:
11703       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11704               "genPointerGet: illegal pointer type");
11705     
11706     }
11707 }
11708
11709 /*-----------------------------------------------------------------*/
11710 /* genPackBits - generates code for packed bit storage             */
11711 /*-----------------------------------------------------------------*/
11712 static void genPackBits (sym_link    *etype , operand *result,
11713                          operand *right ,
11714                          char *rname, int p_type)
11715 {
11716   int shCnt = 0 ;
11717   int offset = 0  ;
11718   int rLen = 0 ;
11719   int blen, bstr ;   
11720   sym_link *retype;
11721   char *l ;
11722
11723         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11724         blen = SPEC_BLEN(etype);
11725         bstr = SPEC_BSTR(etype);
11726
11727         retype = getSpec(operandType(right));
11728
11729         if(AOP_TYPE(right) == AOP_LIT) {
11730                 if((blen == 1) && (bstr < 8)) {
11731                   unsigned long lit;
11732                         /* it is a single bit, so use the appropriate bit instructions */
11733
11734                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11735
11736                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11737 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11738                         if((p_type == POINTER) && (result)) {
11739                                 /* workaround to reduce the extra lfsr instruction */
11740                                 if(lit) {
11741                                         pic16_emitpcode(POC_BSF,
11742                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11743                                 } else {
11744                                         pic16_emitpcode(POC_BCF,
11745                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11746                                 }
11747                         } else {
11748                                 pic16_loadFSR0( result );
11749                                 if(lit) {
11750                                         pic16_emitpcode(POC_BSF,
11751                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11752                                 } else {
11753                                         pic16_emitpcode(POC_BCF,
11754                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11755                                 }
11756                         }
11757         
11758                   return;
11759                 }
11760
11761                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11762                 offset++;
11763         } else
11764         if(IS_BITFIELD(retype) 
11765           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11766           && (blen == 1)) {
11767           int rblen, rbstr;
11768
11769             rblen = SPEC_BLEN( retype );
11770             rbstr = SPEC_BSTR( retype );
11771             
11772
11773             if(IS_BITFIELD(etype)) {
11774               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11775               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11776             } else {
11777               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11778             }
11779             
11780             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11781             
11782             if(IS_BITFIELD(etype)) {
11783               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11784             } else {
11785               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11786             }
11787
11788             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11789             
11790             return;
11791         } else
11792           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11793
11794         /* if the bit lenth is less than or    */
11795         /* it exactly fits a byte then         */
11796         if((shCnt=SPEC_BSTR(etype))
11797                 || SPEC_BLEN(etype) <= 8 )  {
11798
11799                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11800
11801                 /* shift left acc */
11802                 AccLsh(shCnt);
11803
11804                 /* using PRODL as a temporary register here */
11805                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11806
11807                 switch (p_type) {
11808                         case FPOINTER:
11809                         case POINTER:
11810                                 pic16_loadFSR0( result );
11811                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11812 //                              pic16_emitcode ("mov","b,a");
11813 //                              pic16_emitcode("mov","a,@%s",rname);
11814                                 break;
11815
11816                         case GPOINTER:
11817                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11818                                 break;
11819
11820                 }
11821 #if 1
11822                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11823                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11824                                         (unsigned char)(0xff >> (8-bstr))) ));
11825                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11826                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11827 #endif
11828
11829           return;
11830         }
11831
11832
11833         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11834         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11835         exit(-1);
11836
11837
11838     /* if we r done */
11839     if ( SPEC_BLEN(etype) <= 8 )
11840         return ;
11841
11842     pic16_emitcode("inc","%s",rname);
11843     rLen = SPEC_BLEN(etype) ;     
11844
11845
11846
11847     /* now generate for lengths greater than one byte */
11848     while (1) {
11849
11850         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11851
11852         rLen -= 8 ;
11853         if (rLen <= 0 )
11854             break ;
11855
11856         switch (p_type) {
11857             case POINTER:
11858                 if (*l == '@') {
11859                     MOVA(l);
11860                     pic16_emitcode("mov","@%s,a",rname);
11861                 } else
11862                     pic16_emitcode("mov","@%s,%s",rname,l);
11863                 break;
11864
11865             case FPOINTER:
11866                 MOVA(l);
11867                 pic16_emitcode("movx","@dptr,a");
11868                 break;
11869
11870             case GPOINTER:
11871                 MOVA(l);
11872                 DEBUGpic16_emitcode(";lcall","__gptrput");
11873                 break;  
11874         }   
11875         pic16_emitcode ("inc","%s",rname);
11876     }
11877
11878     MOVA(l);
11879
11880     /* last last was not complete */
11881     if (rLen)   {
11882         /* save the byte & read byte */
11883         switch (p_type) {
11884             case POINTER:
11885                 pic16_emitcode ("mov","b,a");
11886                 pic16_emitcode("mov","a,@%s",rname);
11887                 break;
11888
11889             case FPOINTER:
11890                 pic16_emitcode ("mov","b,a");
11891                 pic16_emitcode("movx","a,@dptr");
11892                 break;
11893
11894             case GPOINTER:
11895                 pic16_emitcode ("push","b");
11896                 pic16_emitcode ("push","acc");
11897                 pic16_emitcode ("lcall","__gptrget");
11898                 pic16_emitcode ("pop","b");
11899                 break;
11900         }
11901
11902         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11903         pic16_emitcode ("orl","a,b");
11904     }
11905
11906     if (p_type == GPOINTER)
11907         pic16_emitcode("pop","b");
11908
11909     switch (p_type) {
11910
11911     case POINTER:
11912         pic16_emitcode("mov","@%s,a",rname);
11913         break;
11914         
11915     case FPOINTER:
11916         pic16_emitcode("movx","@dptr,a");
11917         break;
11918         
11919     case GPOINTER:
11920         DEBUGpic16_emitcode(";lcall","__gptrput");
11921         break;                  
11922     }
11923 }
11924 /*-----------------------------------------------------------------*/
11925 /* genDataPointerSet - remat pointer to data space                 */
11926 /*-----------------------------------------------------------------*/
11927 static void genDataPointerSet(operand *right,
11928                               operand *result,
11929                               iCode *ic)
11930 {
11931     int size, offset = 0, resoffset=0 ;
11932
11933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11934     pic16_aopOp(right,ic,FALSE);
11935
11936     size = AOP_SIZE(right);
11937
11938 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11939
11940 #if 0
11941     if ( AOP_TYPE(result) == AOP_PCODE) {
11942       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11943               AOP(result)->aopu.pcop->name,
11944                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11945               PCOR(AOP(result)->aopu.pcop)->instance:
11946               PCOI(AOP(result)->aopu.pcop)->offset);
11947     }
11948 #endif
11949
11950         if(AOP(result)->aopu.pcop->type == PO_DIR)
11951                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11952
11953         while (size--) {
11954                 if (AOP_TYPE(right) == AOP_LIT) {
11955                   unsigned int lit;
11956
11957                     if(!IS_FLOAT(operandType( right )))
11958                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11959                     else {
11960                       union {
11961                         unsigned long lit_int;
11962                         float lit_float;
11963                       } info;
11964         
11965                         /* take care if literal is a float */
11966                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11967                         lit = info.lit_int;
11968                     }
11969
11970                     lit = lit >> (8*offset);
11971                     if(lit&0xff) {
11972                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11973                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11974                     } else {
11975                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11976                     }
11977                 } else {
11978                   pic16_mov2w(AOP(right), offset);
11979                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11980                 }
11981                 offset++;
11982                 resoffset++;
11983         }
11984
11985     pic16_freeAsmop(right,NULL,ic,TRUE);
11986 }
11987
11988
11989
11990 /*-----------------------------------------------------------------*/
11991 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11992 /*-----------------------------------------------------------------*/
11993 static void genNearPointerSet (operand *right,
11994                                operand *result, 
11995                                iCode *ic)
11996 {
11997   asmop *aop = NULL;
11998   char *l;
11999   sym_link *retype;
12000   sym_link *ptype = operandType(result);
12001   sym_link *resetype;
12002     
12003         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12004         retype= getSpec(operandType(right));
12005         resetype = getSpec(operandType(result));
12006   
12007         pic16_aopOp(result,ic,FALSE);
12008     
12009         /* if the result is rematerializable &
12010          * in data space & not a bit variable */
12011         
12012         /* and result is not a bit variable */
12013         if (AOP_TYPE(result) == AOP_PCODE
12014 //              && AOP_TYPE(result) == AOP_IMMD
12015                 && DCL_TYPE(ptype) == POINTER
12016                 && !IS_BITFIELD(retype)
12017                 && !IS_BITFIELD(resetype)) {
12018
12019                 genDataPointerSet (right,result,ic);
12020                 pic16_freeAsmop(result,NULL,ic,TRUE);
12021           return;
12022         }
12023
12024         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12025         pic16_aopOp(right,ic,FALSE);
12026         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12027
12028         /* if the value is already in a pointer register
12029          * then don't need anything more */
12030         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
12031                 /* otherwise get a free pointer register */
12032                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12033
12034 //              if( (AOP_TYPE(result) == AOP_PCODE) 
12035 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12036 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12037                 if(is_LitAOp( AOP(result) ))
12038                 {
12039                   if(!IS_BITFIELD(resetype))
12040                         pic16_loadFSR0( result );  // patch 10
12041                 } else {
12042                   if(!IS_BITFIELD(resetype)) {
12043                         // set up FSR0 with address of result
12044                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12045                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12046                   }
12047                 }
12048
12049         }
12050 //      else
12051 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12052
12053         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12054
12055 //      pic16_loadFSR0( result );
12056
12057         /* if bitfield then unpack the bits */
12058         if (IS_BITFIELD(resetype)) {
12059                 genPackBits (resetype, result, right, NULL, POINTER);
12060         } else {
12061                 /* we have can just get the values */
12062           int size = AOP_SIZE(right);
12063           int offset = 0 ;    
12064
12065                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12066                 while (size--) {
12067                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12068                         if (*l == '@' ) {
12069                                 //MOVA(l);
12070                                 //pic16_emitcode("mov","@%s,a",rname);
12071                                 pic16_emitcode("movf","indf0,w ;1");
12072                         } else {
12073
12074                                 if (AOP_TYPE(right) == AOP_LIT) {
12075                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12076                                         if (size) {
12077                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12078                                         } else {
12079                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12080                                         }
12081                                 } else { // no literal
12082                                         if(size) {
12083                                                 pic16_emitpcode(POC_MOVFF,
12084                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12085                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12086                                         } else {
12087                                                 pic16_emitpcode(POC_MOVFF,
12088                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12089                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12090                                         }
12091                                 }
12092                         }
12093                         offset++;
12094                 }
12095         }
12096
12097         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12098         /* now some housekeeping stuff */
12099         if (aop) {
12100                 /* we had to allocate for this iCode */
12101                 pic16_freeAsmop(NULL,aop,ic,TRUE);
12102         } else { 
12103                 /* we did not allocate which means left
12104                  * already in a pointer register, then
12105                  * if size > 0 && this could be used again
12106                  * we have to point it back to where it 
12107                  * belongs */
12108                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12109                 if (AOP_SIZE(right) > 1
12110                         && !OP_SYMBOL(result)->remat
12111                         && ( OP_SYMBOL(result)->liveTo > ic->seq
12112                                 || ic->depth )) {
12113
12114                   int size = AOP_SIZE(right) - 1;
12115
12116                         while (size--)
12117                                 pic16_emitcode("decf","fsr0,f");
12118                         //pic16_emitcode("dec","%s",rname);
12119                 }
12120         }
12121
12122         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12123         /* done */
12124 //release:
12125         pic16_freeAsmop(right,NULL,ic,TRUE);
12126         pic16_freeAsmop(result,NULL,ic,TRUE);
12127 }
12128
12129 /*-----------------------------------------------------------------*/
12130 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12131 /*-----------------------------------------------------------------*/
12132 static void genPagedPointerSet (operand *right,
12133                                operand *result, 
12134                                iCode *ic)
12135 {
12136     asmop *aop = NULL;
12137     regs *preg = NULL ;
12138     char *rname , *l;
12139     sym_link *retype;
12140        
12141     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12142
12143     retype= getSpec(operandType(right));
12144     
12145     pic16_aopOp(result,ic,FALSE);
12146     
12147     /* if the value is already in a pointer register
12148        then don't need anything more */
12149     if (!AOP_INPREG(AOP(result))) {
12150         /* otherwise get a free pointer register */
12151         aop = newAsmop(0);
12152         preg = getFreePtr(ic,&aop,FALSE);
12153         pic16_emitcode("mov","%s,%s",
12154                 preg->name,
12155                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12156         rname = preg->name ;
12157     } else
12158         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12159     
12160     pic16_freeAsmop(result,NULL,ic,TRUE);
12161     pic16_aopOp (right,ic,FALSE);
12162
12163     /* if bitfield then unpack the bits */
12164     if (IS_BITFIELD(retype)) 
12165         genPackBits (retype,result,right,rname,PPOINTER);
12166     else {
12167         /* we have can just get the values */
12168         int size = AOP_SIZE(right);
12169         int offset = 0 ;        
12170         
12171         while (size--) {
12172             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12173             
12174             MOVA(l);
12175             pic16_emitcode("movx","@%s,a",rname);
12176
12177             if (size)
12178                 pic16_emitcode("inc","%s",rname);
12179
12180             offset++;
12181         }
12182     }
12183     
12184     /* now some housekeeping stuff */
12185     if (aop) {
12186         /* we had to allocate for this iCode */
12187         pic16_freeAsmop(NULL,aop,ic,TRUE);
12188     } else { 
12189         /* we did not allocate which means left
12190            already in a pointer register, then
12191            if size > 0 && this could be used again
12192            we have to point it back to where it 
12193            belongs */
12194         if (AOP_SIZE(right) > 1 &&
12195             !OP_SYMBOL(result)->remat &&
12196             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12197               ic->depth )) {
12198             int size = AOP_SIZE(right) - 1;
12199             while (size--)
12200                 pic16_emitcode("dec","%s",rname);
12201         }
12202     }
12203
12204     /* done */
12205     pic16_freeAsmop(right,NULL,ic,TRUE);
12206     
12207         
12208 }
12209
12210 /*-----------------------------------------------------------------*/
12211 /* genFarPointerSet - set value from far space                     */
12212 /*-----------------------------------------------------------------*/
12213 static void genFarPointerSet (operand *right,
12214                               operand *result, iCode *ic)
12215 {
12216     int size, offset ;
12217     sym_link *retype = getSpec(operandType(right));
12218
12219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12220     pic16_aopOp(result,ic,FALSE);
12221
12222     /* if the operand is already in dptr 
12223     then we do nothing else we move the value to dptr */
12224     if (AOP_TYPE(result) != AOP_STR) {
12225         /* if this is remateriazable */
12226         if (AOP_TYPE(result) == AOP_IMMD)
12227             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12228         else { /* we need to get it byte by byte */
12229             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12230             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12231             if (options.model == MODEL_FLAT24)
12232             {
12233                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12234             }
12235         }
12236     }
12237     /* so dptr know contains the address */
12238     pic16_freeAsmop(result,NULL,ic,TRUE);
12239     pic16_aopOp(right,ic,FALSE);
12240
12241     /* if bit then unpack */
12242     if (IS_BITFIELD(retype)) 
12243         genPackBits(retype,result,right,"dptr",FPOINTER);
12244     else {
12245         size = AOP_SIZE(right);
12246         offset = 0 ;
12247
12248         while (size--) {
12249             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12250             MOVA(l);
12251             pic16_emitcode("movx","@dptr,a");
12252             if (size)
12253                 pic16_emitcode("inc","dptr");
12254         }
12255     }
12256
12257     pic16_freeAsmop(right,NULL,ic,TRUE);
12258 }
12259
12260 /*-----------------------------------------------------------------*/
12261 /* genGenPointerSet - set value from generic pointer space         */
12262 /*-----------------------------------------------------------------*/
12263 #if 0
12264 static void genGenPointerSet (operand *right,
12265                               operand *result, iCode *ic)
12266 {
12267         int i, size, offset, lit;
12268         sym_link *retype = getSpec(operandType(right));
12269
12270         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12271
12272         pic16_aopOp(result,ic,FALSE);
12273         pic16_aopOp(right,ic,FALSE);
12274         size = AOP_SIZE(right);
12275         offset = 0;
12276
12277         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12278
12279         /* if the operand is already in dptr 
12280                 then we do nothing else we move the value to dptr */
12281         if (AOP_TYPE(result) != AOP_STR) {
12282                 /* if this is remateriazable */
12283                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12284                 // WARNING: anythig until "else" is untested!
12285                 if (AOP_TYPE(result) == AOP_IMMD) {
12286                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12287                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12288                         // load FSR0 from immediate
12289                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12290                         offset = 0;
12291                         while(size--) {
12292                                 if(size) {
12293                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12294                                 } else {
12295                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12296                                 }
12297                                 offset++;
12298                         }
12299                         goto release;
12300                 }
12301                 else { /* we need to get it byte by byte */
12302                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12303                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12304
12305                         // set up FSR0 with address of result
12306                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12307                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12308
12309                         /* hack hack! see if this the FSR. If so don't load W */
12310                         if(AOP_TYPE(right) != AOP_ACC) {
12311
12312                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12313
12314                                 if(AOP_TYPE(right) == AOP_LIT)
12315                                 {
12316                                         // copy literal
12317                                         // note: pic16_popGet handles sign extension
12318                                         for(i=0;i<size;i++) {
12319                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12320                                                 if(i < size-1)
12321                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12322                                                 else
12323                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12324                                         }
12325                                 } else {
12326                                         // copy regs
12327
12328                                         for(i=0;i<size;i++) {
12329                                                 if(i < size-1)
12330                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12331                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12332                                                 else
12333                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12334                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12335                                         }
12336                                 }
12337                                 goto release;
12338                         } 
12339                         // right = ACC
12340                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12341                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12342                         goto release;
12343         } // if (AOP_TYPE(result) != AOP_IMMD)
12344
12345         } // if (AOP_TYPE(result) != AOP_STR)
12346         /* so dptr know contains the address */
12347
12348
12349         /* if bit then unpack */
12350         if (IS_BITFIELD(retype)) 
12351                 genPackBits(retype,result,right,"dptr",GPOINTER);
12352         else {
12353                 size = AOP_SIZE(right);
12354                 offset = 0 ;
12355
12356                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12357
12358                 // set up FSR0 with address of result
12359                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12360                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12361         
12362                 while (size--) {
12363                         if (AOP_TYPE(right) == AOP_LIT) {
12364                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12365                                 if (size) {
12366                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12367                                 } else {
12368                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12369                                 }
12370                         } else { // no literal
12371                                 if(size) {
12372                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12373                                 } else {
12374                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12375                                 }
12376                         }
12377                         offset++;
12378                 }
12379         }
12380
12381         release:
12382         pic16_freeAsmop(right,NULL,ic,TRUE);
12383         pic16_freeAsmop(result,NULL,ic,TRUE);
12384 }
12385 #endif
12386
12387 static void genGenPointerSet (operand *right,
12388                               operand *result, iCode *ic)
12389 {
12390   int size;
12391   sym_link *retype = getSpec(operandType(right));
12392   char fgptrput[32];
12393
12394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12395
12396     pic16_aopOp(result,ic,FALSE);
12397     pic16_aopOp(right,ic,FALSE);
12398     size = AOP_SIZE(right);
12399
12400     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12401
12402
12403     /* if bit then unpack */
12404     if (IS_BITFIELD(retype)) {
12405 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12406       genPackBits(retype,result,right,"dptr",GPOINTER);
12407       goto release;
12408     }
12409
12410     size = AOP_SIZE(right);
12411
12412     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12413
12414
12415
12416     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12417
12418     /* value of right+0 is placed on stack, which will be retrieved
12419      * by the support function this restoring the stack. The important
12420      * thing is that there is no need to manually restore stack pointer
12421      * here */
12422     pushaop(AOP(right), 0);
12423 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12424     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12425     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12426     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12427     
12428     /* load address to write to in WREG:FSR0H:FSR0L */
12429     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12430                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12431     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12432                                 pic16_popCopyReg(&pic16_pc_prodl)));
12433     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12434     
12435
12436     /* put code here */
12437     switch (size) {
12438       case 1: strcpy(fgptrput, "__gptrput1"); break;
12439       case 2: strcpy(fgptrput, "__gptrput2"); break;
12440       case 3: strcpy(fgptrput, "__gptrput3"); break;
12441       case 4: strcpy(fgptrput, "__gptrput4"); break;
12442       default:
12443         werror(W_POSSBUG2, __FILE__, __LINE__);
12444         abort();
12445     }
12446     
12447     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12448     
12449     {
12450       symbol *sym;
12451                   
12452         sym = newSymbol( fgptrput, 0 );
12453         strcpy(sym->rname, fgptrput);
12454         checkAddSym(&externs, sym);
12455     }
12456
12457 release:
12458     pic16_freeAsmop(right,NULL,ic,TRUE);
12459     pic16_freeAsmop(result,NULL,ic,TRUE);
12460 }
12461
12462 /*-----------------------------------------------------------------*/
12463 /* genPointerSet - stores the value into a pointer location        */
12464 /*-----------------------------------------------------------------*/
12465 static void genPointerSet (iCode *ic)
12466 {    
12467   operand *right, *result ;
12468   sym_link *type, *etype;
12469   int p_type;
12470
12471     FENTRY;
12472
12473     right = IC_RIGHT(ic);
12474     result = IC_RESULT(ic) ;
12475
12476     /* depending on the type of pointer we need to
12477     move it to the correct pointer register */
12478     type = operandType(result);
12479     etype = getSpec(type);
12480     /* if left is of type of pointer then it is simple */
12481     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12482         p_type = DCL_TYPE(type);
12483     }
12484     else {
12485         /* we have to go by the storage class */
12486         p_type = PTR_TYPE(SPEC_OCLS(etype));
12487
12488 /*      if (SPEC_OCLS(etype)->codesp ) { */
12489 /*          p_type = CPOINTER ;  */
12490 /*      } */
12491 /*      else */
12492 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12493 /*              p_type = FPOINTER ; */
12494 /*          else */
12495 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12496 /*                  p_type = PPOINTER ; */
12497 /*              else */
12498 /*                  if (SPEC_OCLS(etype) == idata ) */
12499 /*                      p_type = IPOINTER ; */
12500 /*                  else */
12501 /*                      p_type = POINTER ; */
12502     }
12503
12504     /* now that we have the pointer type we assign
12505     the pointer values */
12506     switch (p_type) {
12507       case POINTER:
12508       case IPOINTER:
12509         genNearPointerSet (right,result,ic);
12510         break;
12511
12512       case PPOINTER:
12513         genPagedPointerSet (right,result,ic);
12514         break;
12515
12516       case FPOINTER:
12517         genFarPointerSet (right,result,ic);
12518         break;
12519         
12520       case GPOINTER:
12521         genGenPointerSet (right,result,ic);
12522         break;
12523
12524       default:
12525         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12526           "genPointerSet: illegal pointer type");
12527     }
12528 }
12529
12530 /*-----------------------------------------------------------------*/
12531 /* genIfx - generate code for Ifx statement                        */
12532 /*-----------------------------------------------------------------*/
12533 static void genIfx (iCode *ic, iCode *popIc)
12534 {
12535   operand *cond = IC_COND(ic);
12536   int isbit =0;
12537
12538     FENTRY;
12539
12540     pic16_aopOp(cond,ic,FALSE);
12541
12542     /* get the value into acc */
12543     if (AOP_TYPE(cond) != AOP_CRY)
12544       pic16_toBoolean(cond);
12545     else
12546       isbit = 1;
12547     /* the result is now in the accumulator */
12548     pic16_freeAsmop(cond,NULL,ic,TRUE);
12549
12550     /* if there was something to be popped then do it */
12551     if (popIc)
12552       genIpop(popIc);
12553
12554     /* if the condition is  a bit variable */
12555     if (isbit && IS_ITEMP(cond) && 
12556         SPIL_LOC(cond)) {
12557       genIfxJump(ic,"c");
12558       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12559     } else {
12560       if (isbit && !IS_ITEMP(cond))
12561         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12562         else
12563         genIfxJump(ic,"a");
12564     }
12565     ic->generated = 1;
12566 }
12567
12568 /*-----------------------------------------------------------------*/
12569 /* genAddrOf - generates code for address of                       */
12570 /*-----------------------------------------------------------------*/
12571 static void genAddrOf (iCode *ic)
12572 {
12573   operand *result, *left;
12574   int size;
12575   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12576   pCodeOp *pcop0, *pcop1, *pcop2;
12577
12578     FENTRY;
12579
12580     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12581
12582     sym = OP_SYMBOL( IC_LEFT(ic) );
12583     
12584     if(sym->onStack) {
12585       /* get address of symbol on stack */
12586       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12587 #if 0
12588       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12589                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12590 #endif
12591
12592       // operands on stack are accessible via "FSR2 + index" with index
12593       // starting at 2 for arguments and growing from 0 downwards for
12594       // local variables (index == 0 is not assigned so we add one here)
12595       {
12596         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12597         if (soffs <= 0) {
12598           assert (soffs < 0);
12599           soffs++;
12600         } // if
12601         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12602         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12603         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12604         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12605         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12606         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12607         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12608       }
12609
12610       goto release;
12611     }
12612         
12613 //      if(pic16_debug_verbose) {
12614 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12615 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12616 //      }
12617         
12618     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12619     size = AOP_SIZE(IC_RESULT(ic));
12620
12621     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12622     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12623     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12624         
12625     if (size == 3) {
12626       pic16_emitpcode(POC_MOVLW, pcop0);
12627       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12628       pic16_emitpcode(POC_MOVLW, pcop1);
12629       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12630       pic16_emitpcode(POC_MOVLW, pcop2);
12631       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12632     } else
12633     if (size == 2) {
12634       pic16_emitpcode(POC_MOVLW, pcop0);
12635       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12636       pic16_emitpcode(POC_MOVLW, pcop1);
12637     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12638     } else {
12639       pic16_emitpcode(POC_MOVLW, pcop0);
12640       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12641     }
12642
12643     pic16_freeAsmop(left, NULL, ic, FALSE);
12644 release:
12645     pic16_freeAsmop(result,NULL,ic,TRUE);
12646 }
12647
12648
12649 #if 0
12650 /*-----------------------------------------------------------------*/
12651 /* genFarFarAssign - assignment when both are in far space         */
12652 /*-----------------------------------------------------------------*/
12653 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12654 {
12655     int size = AOP_SIZE(right);
12656     int offset = 0;
12657     char *l ;
12658     /* first push the right side on to the stack */
12659     while (size--) {
12660         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12661         MOVA(l);
12662         pic16_emitcode ("push","acc");
12663     }
12664     
12665     pic16_freeAsmop(right,NULL,ic,FALSE);
12666     /* now assign DPTR to result */
12667     pic16_aopOp(result,ic,FALSE);
12668     size = AOP_SIZE(result);
12669     while (size--) {
12670         pic16_emitcode ("pop","acc");
12671         pic16_aopPut(AOP(result),"a",--offset);
12672     }
12673     pic16_freeAsmop(result,NULL,ic,FALSE);
12674         
12675 }
12676 #endif
12677
12678 /*-----------------------------------------------------------------*/
12679 /* genAssign - generate code for assignment                        */
12680 /*-----------------------------------------------------------------*/
12681 static void genAssign (iCode *ic)
12682 {
12683   operand *result, *right;
12684   int size, offset,know_W;
12685   unsigned long lit = 0L;
12686
12687   result = IC_RESULT(ic);
12688   right  = IC_RIGHT(ic) ;
12689
12690   FENTRY;
12691   
12692   /* if they are the same */
12693   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12694     return ;
12695
12696   /* reversed order operands are aopOp'ed so that result operand
12697    * is effective in case right is a stack symbol. This maneauver
12698    * allows to use the _G.resDirect flag later */
12699   pic16_aopOp(result,ic,TRUE);
12700   pic16_aopOp(right,ic,FALSE);
12701
12702   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12703
12704   /* if they are the same registers */
12705   if (pic16_sameRegs(AOP(right),AOP(result)))
12706     goto release;
12707
12708   /* if the result is a bit */
12709   if (AOP_TYPE(result) == AOP_CRY) {
12710     /* if the right size is a literal then
12711        we know what the value is */
12712     if (AOP_TYPE(right) == AOP_LIT) {
12713           
12714       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12715                   pic16_popGet(AOP(result),0));
12716
12717       if (((int) operandLitValue(right))) 
12718         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12719                        AOP(result)->aopu.aop_dir,
12720                        AOP(result)->aopu.aop_dir);
12721       else
12722         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12723                        AOP(result)->aopu.aop_dir,
12724                        AOP(result)->aopu.aop_dir);
12725       goto release;
12726     }
12727
12728     /* the right is also a bit variable */
12729     if (AOP_TYPE(right) == AOP_CRY) {
12730       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12731       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12732       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12733
12734       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12735                      AOP(result)->aopu.aop_dir,
12736                      AOP(result)->aopu.aop_dir);
12737       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12738                      AOP(right)->aopu.aop_dir,
12739                      AOP(right)->aopu.aop_dir);
12740       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12741                      AOP(result)->aopu.aop_dir,
12742                      AOP(result)->aopu.aop_dir);
12743       goto release ;
12744     }
12745
12746     /* we need to or */
12747     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12748     pic16_toBoolean(right);
12749     emitSKPZ;
12750     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12751     //pic16_aopPut(AOP(result),"a",0);
12752     goto release ;
12753   }
12754
12755   /* bit variables done */
12756   /* general case */
12757   size = AOP_SIZE(result);
12758   offset = 0 ;
12759
12760   if(AOP_TYPE(right) == AOP_LIT) {
12761         if(!IS_FLOAT(operandType( right )))
12762                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12763         else {
12764            union {
12765               unsigned long lit_int;
12766               float lit_float;
12767             } info;
12768         
12769                 /* take care if literal is a float */
12770                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12771                 lit = info.lit_int;
12772         }
12773   }
12774
12775 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12776 //                      sizeof(unsigned long int), sizeof(float));
12777
12778
12779   if (AOP_TYPE(right) == AOP_REG) {
12780     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12781     while (size--) {
12782       
12783       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12784     } // while
12785     goto release;
12786   }
12787
12788   if(AOP_TYPE(right) != AOP_LIT
12789         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12790         && !IS_FUNC(OP_SYM_TYPE(right))
12791         ) {
12792         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12793         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12794
12795         // set up table pointer
12796         if(is_LitOp(right)) {
12797 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12798                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12799                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12800                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12801                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12802                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12803                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12804         } else {
12805 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12806                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12807                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12808                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12809                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12810                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12811                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12812         }
12813
12814         size = min(AOP_SIZE(right), AOP_SIZE(result));
12815         while(size--) {
12816                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12817                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12818                         pic16_popGet(AOP(result),offset)));
12819                 offset++;
12820         }
12821
12822         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12823                 size = AOP_SIZE(result) - AOP_SIZE(right);
12824                 while(size--) {
12825                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12826                         offset++;
12827                 }
12828         }
12829         goto release;
12830   }
12831
12832
12833
12834 #if 0
12835 /* VR - What is this?! */
12836   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12837     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12838     if(aopIdx(AOP(result),0) == 4) {
12839
12840       /* this is a workaround to save value of right into wreg too,
12841        * value of wreg is going to be used later */
12842       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12843       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12844       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12845       goto release;
12846     } else
12847 //      assert(0);
12848       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12849   }
12850 #endif
12851
12852   know_W=-1;
12853   while (size--) {
12854   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12855     if(AOP_TYPE(right) == AOP_LIT) {
12856       if(lit&0xff) {
12857         if(know_W != (lit&0xff))
12858           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12859         know_W = lit&0xff;
12860         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12861       } else
12862         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12863
12864       lit >>= 8;
12865
12866     } else if (AOP_TYPE(right) == AOP_CRY) {
12867       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12868       if(offset == 0) {
12869         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12870         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12871         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12872       }
12873     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12874         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12875         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12876     } else {
12877       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12878
12879       if(!_G.resDirect)         /* use this aopForSym feature */
12880         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12881     }
12882             
12883     offset++;
12884   }
12885   
12886  release:
12887   pic16_freeAsmop (right,NULL,ic,FALSE);
12888   pic16_freeAsmop (result,NULL,ic,TRUE);
12889 }   
12890
12891 /*-----------------------------------------------------------------*/
12892 /* genJumpTab - generates code for jump table                       */
12893 /*-----------------------------------------------------------------*/
12894 static void genJumpTab (iCode *ic)
12895 {
12896   symbol *jtab;
12897   char *l;
12898   pCodeOp *jt_offs;
12899   pCodeOp *jt_offs_hi;
12900   pCodeOp *jt_label;
12901
12902     FENTRY;
12903
12904     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12905     /* get the condition into accumulator */
12906     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12907     MOVA(l);
12908     /* multiply by three */
12909     pic16_emitcode("add","a,acc");
12910     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12911
12912     jtab = newiTempLabel(NULL);
12913     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12914     pic16_emitcode("jmp","@a+dptr");
12915     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12916
12917 #if 0
12918     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12919     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12920     emitSKPNC;
12921     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12922     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12923     pic16_emitpLabel(jtab->key);
12924
12925 #else
12926
12927     jt_offs = pic16_popGetTempReg(0);
12928     jt_offs_hi = pic16_popGetTempReg(1);
12929     jt_label = pic16_popGetLabel (jtab->key);
12930     //fprintf (stderr, "Creating jump table...\n");
12931
12932     // calculate offset into jump table (idx * sizeof (GOTO))
12933     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12934     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12935     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12936     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12937     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12938     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12939     pic16_emitpcode(POC_MOVWF , jt_offs);
12940
12941     // prepare PCLATx (set to first entry in jump table)
12942     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12943     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12944     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12945     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12946     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12947
12948     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12949     pic16_emitpcode(POC_ADDWF , jt_offs);
12950     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12951     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12952     emitSKPNC;
12953     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12954
12955     // release temporaries and prepare jump into table (new PCL --> WREG)
12956     pic16_emitpcode(POC_MOVFW , jt_offs);
12957     pic16_popReleaseTempReg (jt_offs_hi, 1);
12958     pic16_popReleaseTempReg (jt_offs, 0);
12959
12960     // jump into the table
12961     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12962
12963     pic16_emitpLabelFORCE(jtab->key);
12964
12965 #endif
12966     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12967
12968     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12969     /* now generate the jump labels */
12970     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12971          jtab = setNextItem(IC_JTLABELS(ic))) {
12972 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12973         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12974         
12975     }
12976     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12977
12978 }
12979
12980 /*-----------------------------------------------------------------*/
12981 /* genMixedOperation - gen code for operators between mixed types  */
12982 /*-----------------------------------------------------------------*/
12983 /*
12984   TSD - Written for the PIC port - but this unfortunately is buggy.
12985   This routine is good in that it is able to efficiently promote 
12986   types to different (larger) sizes. Unfortunately, the temporary
12987   variables that are optimized out by this routine are sometimes
12988   used in other places. So until I know how to really parse the 
12989   iCode tree, I'm going to not be using this routine :(.
12990 */
12991 static int genMixedOperation (iCode *ic)
12992 {
12993 #if 0
12994   operand *result = IC_RESULT(ic);
12995   sym_link *ctype = operandType(IC_LEFT(ic));
12996   operand *right = IC_RIGHT(ic);
12997   int ret = 0;
12998   int big,small;
12999   int offset;
13000
13001   iCode *nextic;
13002   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13003
13004   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13005
13006   nextic = ic->next;
13007   if(!nextic)
13008     return 0;
13009
13010   nextright = IC_RIGHT(nextic);
13011   nextleft  = IC_LEFT(nextic);
13012   nextresult = IC_RESULT(nextic);
13013
13014   pic16_aopOp(right,ic,FALSE);
13015   pic16_aopOp(result,ic,FALSE);
13016   pic16_aopOp(nextright,  nextic, FALSE);
13017   pic16_aopOp(nextleft,   nextic, FALSE);
13018   pic16_aopOp(nextresult, nextic, FALSE);
13019
13020   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13021
13022     operand *t = right;
13023     right = nextright;
13024     nextright = t; 
13025
13026     pic16_emitcode(";remove right +","");
13027
13028   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13029 /*
13030     operand *t = right;
13031     right = nextleft;
13032     nextleft = t; 
13033 */
13034     pic16_emitcode(";remove left +","");
13035   } else
13036     return 0;
13037
13038   big = AOP_SIZE(nextleft);
13039   small = AOP_SIZE(nextright);
13040
13041   switch(nextic->op) {
13042
13043   case '+':
13044     pic16_emitcode(";optimize a +","");
13045     /* if unsigned or not an integral type */
13046     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13047       pic16_emitcode(";add a bit to something","");
13048     } else {
13049
13050       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13051
13052       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13053         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13054         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13055       } else
13056         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13057
13058       offset = 0;
13059       while(--big) {
13060
13061         offset++;
13062
13063         if(--small) {
13064           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13065             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13066             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13067           }
13068
13069           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13070           emitSKPNC;
13071           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13072                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13073                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13074           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13075           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13076
13077         } else {
13078           pic16_emitcode("rlf","known_zero,w");
13079
13080           /*
13081             if right is signed
13082               btfsc  right,7
13083                addlw ff
13084           */
13085           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13086             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13087             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13088           } else {
13089             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13090           }
13091         }
13092       }
13093       ret = 1;
13094     }
13095   }
13096   ret = 1;
13097
13098 release:
13099   pic16_freeAsmop(right,NULL,ic,TRUE);
13100   pic16_freeAsmop(result,NULL,ic,TRUE);
13101   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13102   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13103   if(ret)
13104     nextic->generated = 1;
13105
13106   return ret;
13107 #else
13108   return 0;
13109 #endif
13110 }
13111 /*-----------------------------------------------------------------*/
13112 /* genCast - gen code for casting                                  */
13113 /*-----------------------------------------------------------------*/
13114 static void genCast (iCode *ic)
13115 {
13116   operand *result = IC_RESULT(ic);
13117   sym_link *ctype = operandType(IC_LEFT(ic));
13118   sym_link *rtype = operandType(IC_RIGHT(ic));
13119   sym_link *restype = operandType(IC_RESULT(ic));
13120   operand *right = IC_RIGHT(ic);
13121   int size, offset ;
13122
13123
13124     FENTRY;
13125
13126         /* if they are equivalent then do nothing */
13127 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13128 //              return ;
13129
13130         pic16_aopOp(right,ic,FALSE) ;
13131         pic16_aopOp(result,ic,FALSE);
13132
13133         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13134
13135
13136         /* if the result is a bit */
13137         if (AOP_TYPE(result) == AOP_CRY) {
13138         
13139                 /* if the right size is a literal then
13140                  * we know what the value is */
13141                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13142
13143                 if (AOP_TYPE(right) == AOP_LIT) {
13144                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13145                                 pic16_popGet(AOP(result),0));
13146
13147                         if (((int) operandLitValue(right))) 
13148                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13149                                         AOP(result)->aopu.aop_dir,
13150                                         AOP(result)->aopu.aop_dir);
13151                         else
13152                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13153                                         AOP(result)->aopu.aop_dir,
13154                                         AOP(result)->aopu.aop_dir);
13155                         goto release;
13156                 }
13157
13158                 /* the right is also a bit variable */
13159                 if (AOP_TYPE(right) == AOP_CRY) {
13160                         emitCLRC;
13161                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13162
13163                         pic16_emitcode("clrc","");
13164                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13165                                 AOP(right)->aopu.aop_dir,
13166                                 AOP(right)->aopu.aop_dir);
13167                         pic16_aopPut(AOP(result),"c",0);
13168                         goto release ;
13169                 }
13170
13171                 /* we need to or */
13172                 if (AOP_TYPE(right) == AOP_REG) {
13173                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13174                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13175                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13176                 }
13177                 pic16_toBoolean(right);
13178                 pic16_aopPut(AOP(result),"a",0);
13179                 goto release ;
13180         }
13181
13182         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13183           int offset = 1;
13184
13185                 size = AOP_SIZE(result);
13186
13187                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13188
13189                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13190                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13191                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13192
13193                 while (size--)
13194                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13195
13196                 goto release;
13197         }
13198
13199         if(IS_BITFIELD(getSpec(restype))
13200           && IS_BITFIELD(getSpec(rtype))) {
13201           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13202         }
13203
13204         /* if they are the same size : or less */
13205         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13206
13207                 /* if they are in the same place */
13208                 if (pic16_sameRegs(AOP(right),AOP(result)))
13209                         goto release;
13210
13211                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13212 #if 0
13213                 if (IS_PTR_CONST(rtype))
13214 #else
13215                 if (IS_CODEPTR(rtype))
13216 #endif
13217                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13218
13219 #if 0
13220                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13221 #else
13222                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13223 #endif
13224                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13225
13226 #if 0
13227                 if(AOP_TYPE(right) == AOP_IMMD) {
13228                   pCodeOp *pcop0, *pcop1, *pcop2;
13229                   symbol *sym = OP_SYMBOL( right );
13230
13231                         size = AOP_SIZE(result);
13232                         /* low */
13233                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13234                         /* high */
13235                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13236                         /* upper */
13237                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13238         
13239                         if (size == 3) {
13240                                 pic16_emitpcode(POC_MOVLW, pcop0);
13241                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13242                                 pic16_emitpcode(POC_MOVLW, pcop1);
13243                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13244                                 pic16_emitpcode(POC_MOVLW, pcop2);
13245                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13246                         } else
13247                         if (size == 2) {
13248                                 pic16_emitpcode(POC_MOVLW, pcop0);
13249                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13250                                 pic16_emitpcode(POC_MOVLW, pcop1);
13251                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13252                         } else {
13253                                 pic16_emitpcode(POC_MOVLW, pcop0);
13254                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13255                         }
13256                 } else
13257 #endif
13258                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13259                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13260                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13261                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13262                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13263                         if(AOP_SIZE(result) <2)
13264                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13265                 } else {
13266                         /* if they in different places then copy */
13267                         size = AOP_SIZE(result);
13268                         offset = 0 ;
13269                         while (size--) {
13270                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13271                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13272                                 offset++;
13273                         }
13274                 }
13275                 goto release;
13276         }
13277
13278         /* if the result is of type pointer */
13279         if (IS_PTR(ctype)) {
13280           int p_type;
13281           sym_link *type = operandType(right);
13282           sym_link *etype = getSpec(type);
13283
13284                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13285
13286                 /* pointer to generic pointer */
13287                 if (IS_GENPTR(ctype)) {
13288                   char *l = zero;
13289             
13290                         if (IS_PTR(type)) 
13291                                 p_type = DCL_TYPE(type);
13292                         else {
13293                 /* we have to go by the storage class */
13294                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13295
13296 /*              if (SPEC_OCLS(etype)->codesp )  */
13297 /*                  p_type = CPOINTER ;  */
13298 /*              else */
13299 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13300 /*                      p_type = FPOINTER ; */
13301 /*                  else */
13302 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13303 /*                          p_type = PPOINTER; */
13304 /*                      else */
13305 /*                          if (SPEC_OCLS(etype) == idata ) */
13306 /*                              p_type = IPOINTER ; */
13307 /*                          else */
13308 /*                              p_type = POINTER ; */
13309             }
13310                 
13311             /* the first two bytes are known */
13312       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13313             size = GPTRSIZE - 1; 
13314             offset = 0 ;
13315             while (size--) {
13316               if(offset < AOP_SIZE(right)) {
13317                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13318                 mov2f(AOP(result), AOP(right), offset);
13319 /*
13320                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13321                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13322                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13323                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13324                 } else { 
13325                   
13326                   pic16_aopPut(AOP(result),
13327                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13328                          offset);
13329                 }
13330 */
13331               } else 
13332                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13333               offset++;
13334             }
13335             /* the last byte depending on type */
13336             switch (p_type) {
13337             case IPOINTER:
13338             case POINTER:
13339                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13340                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13341 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13342                 break;
13343
13344             case CPOINTER:
13345                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13346                 break;
13347
13348             case FPOINTER:
13349               pic16_emitcode(";BUG!? ","%d",__LINE__);
13350                 l = one;
13351                 break;
13352             case PPOINTER:
13353               pic16_emitcode(";BUG!? ","%d",__LINE__);
13354                 l = "#0x03";
13355                 break;
13356
13357             case GPOINTER:
13358                 if (GPTRSIZE > AOP_SIZE(right)) {
13359                   // assume data pointer... THIS MIGHT BE WRONG!
13360                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13361                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13362                 } else {
13363                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13364                 }
13365               break;
13366               
13367             default:
13368                 /* this should never happen */
13369                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13370                        "got unknown pointer type");
13371                 exit(1);
13372             }
13373             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13374             goto release ;
13375         }
13376         
13377         /* just copy the pointers */
13378         size = AOP_SIZE(result);
13379         offset = 0 ;
13380         while (size--) {
13381             pic16_aopPut(AOP(result),
13382                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13383                    offset);
13384             offset++;
13385         }
13386         goto release ;
13387     }
13388     
13389
13390
13391     /* so we now know that the size of destination is greater
13392     than the size of the source.
13393     Now, if the next iCode is an operator then we might be
13394     able to optimize the operation without performing a cast.
13395     */
13396     if(genMixedOperation(ic))
13397       goto release;
13398
13399     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13400     
13401     /* we move to result for the size of source */
13402     size = AOP_SIZE(right);
13403     offset = 0 ;
13404     while (size--) {
13405       mov2f(AOP(result), AOP(right), offset);
13406       offset++;
13407     }
13408
13409     /* now depending on the sign of the destination */
13410     size = AOP_SIZE(result) - AOP_SIZE(right);
13411     /* if unsigned or not an integral type */
13412     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13413       while (size--)
13414         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13415     } else {
13416       /* we need to extend the sign :( */
13417
13418       if(size == 1) {
13419         /* Save one instruction of casting char to int */
13420         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13421         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13422         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13423       } else {
13424         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13425
13426         if(offset)
13427           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13428         else
13429           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13430         
13431         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13432
13433         while (size--)
13434           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13435       }
13436     }
13437
13438 release:
13439     pic16_freeAsmop(right,NULL,ic,TRUE);
13440     pic16_freeAsmop(result,NULL,ic,TRUE);
13441
13442 }
13443
13444 /*-----------------------------------------------------------------*/
13445 /* genDjnz - generate decrement & jump if not zero instrucion      */
13446 /*-----------------------------------------------------------------*/
13447 static int genDjnz (iCode *ic, iCode *ifx)
13448 {
13449     symbol *lbl, *lbl1;
13450     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13451
13452     if (!ifx)
13453         return 0;
13454     
13455     /* if the if condition has a false label
13456        then we cannot save */
13457     if (IC_FALSE(ifx))
13458         return 0;
13459
13460     /* if the minus is not of the form 
13461        a = a - 1 */
13462     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13463         !IS_OP_LITERAL(IC_RIGHT(ic)))
13464         return 0;
13465
13466     if (operandLitValue(IC_RIGHT(ic)) != 1)
13467         return 0;
13468
13469     /* if the size of this greater than one then no
13470        saving */
13471     if (getSize(operandType(IC_RESULT(ic))) > 1)
13472         return 0;
13473
13474     /* otherwise we can save BIG */
13475     lbl = newiTempLabel(NULL);
13476     lbl1= newiTempLabel(NULL);
13477
13478     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13479     
13480     if (IS_AOP_PREG(IC_RESULT(ic))) {
13481         pic16_emitcode("dec","%s",
13482                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13483         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13484         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13485     } else {    
13486
13487
13488       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13489       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13490
13491       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13492       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13493
13494     }
13495     
13496     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13497     ifx->generated = 1;
13498     return 1;
13499 }
13500
13501 /*-----------------------------------------------------------------*/
13502 /* genReceive - generate code for a receive iCode                  */
13503 /*-----------------------------------------------------------------*/
13504 static void genReceive (iCode *ic)
13505 {    
13506
13507   FENTRY;
13508
13509 #if 0
13510   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13511         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13512 #endif
13513 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13514
13515   if (isOperandInFarSpace(IC_RESULT(ic))
13516       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13517           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13518
13519     int size = getSize(operandType(IC_RESULT(ic)));
13520     int offset =  pic16_fReturnSizePic - size;
13521
13522       assert( 0 );
13523       while (size--) {
13524         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13525                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13526                       offset++;
13527         }
13528
13529       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13530
13531       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13532       size = AOP_SIZE(IC_RESULT(ic));
13533       offset = 0;
13534       while (size--) {
13535         pic16_emitcode ("pop","acc");
13536         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13537       }
13538   } else {
13539     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13540     _G.accInUse++;
13541     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13542     _G.accInUse--;
13543
13544     /* set pseudo stack pointer to where it should be - dw*/
13545     GpsuedoStkPtr = ic->parmBytes;
13546
13547     /* setting GpsuedoStkPtr has side effects here: */
13548     assignResultValue(IC_RESULT(ic), 0);
13549   }
13550
13551   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13552 }
13553
13554 /*-----------------------------------------------------------------*/
13555 /* genDummyRead - generate code for dummy read of volatiles        */
13556 /*-----------------------------------------------------------------*/
13557 static void
13558 genDummyRead (iCode * ic)
13559 {
13560   pic16_emitcode ("; genDummyRead","");
13561   pic16_emitcode ("; not implemented","");
13562
13563   ic = ic;
13564 }
13565
13566 /*-----------------------------------------------------------------*/
13567 /* genpic16Code - generate code for pic16 based controllers        */
13568 /*-----------------------------------------------------------------*/
13569 /*
13570  * At this point, ralloc.c has gone through the iCode and attempted
13571  * to optimize in a way suitable for a PIC. Now we've got to generate
13572  * PIC instructions that correspond to the iCode.
13573  *
13574  * Once the instructions are generated, we'll pass through both the
13575  * peep hole optimizer and the pCode optimizer.
13576  *-----------------------------------------------------------------*/
13577
13578 void genpic16Code (iCode *lic)
13579 {
13580   iCode *ic;
13581   int cln = 0;
13582
13583     lineHead = lineCurr = NULL;
13584
13585     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13586     pic16_addpBlock(pb);
13587
13588 #if 0
13589     /* if debug information required */
13590     if (options.debug && currFunc) {
13591       if (currFunc) {
13592         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13593       }
13594     }
13595 #endif
13596
13597     for (ic = lic ; ic ; ic = ic->next ) {
13598
13599       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13600       if ( cln != ic->lineno ) {
13601         if ( options.debug ) {
13602           debugFile->writeCLine (ic);
13603         }
13604         
13605         if(!options.noCcodeInAsm) {
13606           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13607               printCLine(ic->filename, ic->lineno)));
13608         }
13609
13610         cln = ic->lineno ;
13611       }
13612         
13613       if(options.iCodeInAsm) {
13614         char *l;
13615
13616           /* insert here code to print iCode as comment */
13617           l = Safe_strdup(printILine(ic));
13618           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13619       }
13620         
13621       /* if the result is marked as
13622        * spilt and rematerializable or code for
13623        * this has already been generated then
13624        * do nothing */
13625       if (resultRemat(ic) || ic->generated ) 
13626         continue ;
13627         
13628       /* depending on the operation */
13629       switch (ic->op) {
13630         case '!' :
13631           pic16_genNot(ic);
13632           break;
13633             
13634         case '~' :
13635           pic16_genCpl(ic);
13636           break;
13637             
13638         case UNARYMINUS:
13639           genUminus (ic);
13640           break;
13641             
13642         case IPUSH:
13643           genIpush (ic);
13644           break;
13645             
13646         case IPOP:
13647           /* IPOP happens only when trying to restore a 
13648            * spilt live range, if there is an ifx statement
13649            * following this pop then the if statement might
13650            * be using some of the registers being popped which
13651            * would destroy the contents of the register so
13652            * we need to check for this condition and handle it */
13653            if (ic->next
13654              && ic->next->op == IFX
13655              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13656                genIfx (ic->next,ic);
13657           else
13658             genIpop (ic);
13659           break; 
13660             
13661         case CALL:
13662           genCall (ic);
13663           break;
13664             
13665         case PCALL:
13666           genPcall (ic);
13667           break;
13668             
13669         case FUNCTION:
13670           genFunction (ic);
13671           break;
13672             
13673         case ENDFUNCTION:
13674           genEndFunction (ic);
13675           break;
13676             
13677         case RETURN:
13678           genRet (ic);
13679           break;
13680             
13681         case LABEL:
13682           genLabel (ic);
13683           break;
13684             
13685         case GOTO:
13686           genGoto (ic);
13687           break;
13688             
13689         case '+' :
13690           pic16_genPlus (ic) ;
13691           break;
13692             
13693         case '-' :
13694           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13695             pic16_genMinus (ic);
13696           break;
13697
13698         case '*' :
13699           genMult (ic);
13700           break;
13701             
13702         case '/' :
13703           genDiv (ic) ;
13704           break;
13705             
13706         case '%' :
13707           genMod (ic);
13708           break;
13709             
13710         case '>' :
13711           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13712           break;
13713             
13714         case '<' :
13715           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13716           break;
13717             
13718         case LE_OP:
13719         case GE_OP:
13720         case NE_OP:
13721           /* note these two are xlated by algebraic equivalence
13722            * during parsing SDCC.y */
13723           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13724             "got '>=' or '<=' shouldn't have come here");
13725           break;
13726
13727         case EQ_OP:
13728           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13729           break;            
13730             
13731         case AND_OP:
13732           genAndOp (ic);
13733           break;
13734             
13735         case OR_OP:
13736           genOrOp (ic);
13737           break;
13738             
13739         case '^' :
13740           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13741           break;
13742             
13743         case '|' :
13744           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13745           break;
13746             
13747         case BITWISEAND:
13748           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13749           break;
13750             
13751         case INLINEASM:
13752           genInline (ic);
13753           break;
13754             
13755         case RRC:
13756           genRRC (ic);
13757           break;
13758             
13759         case RLC:
13760           genRLC (ic);
13761           break;
13762             
13763         case GETHBIT:
13764           genGetHbit (ic);
13765           break;
13766             
13767         case LEFT_OP:
13768           genLeftShift (ic);
13769           break;
13770             
13771         case RIGHT_OP:
13772           genRightShift (ic);
13773           break;
13774             
13775         case GET_VALUE_AT_ADDRESS:
13776           genPointerGet(ic);
13777           break;
13778             
13779         case '=' :
13780           if (POINTER_SET(ic))
13781             genPointerSet(ic);
13782           else
13783             genAssign(ic);
13784           break;
13785             
13786         case IFX:
13787           genIfx (ic,NULL);
13788           break;
13789             
13790         case ADDRESS_OF:
13791           genAddrOf (ic);
13792           break;
13793             
13794         case JUMPTABLE:
13795           genJumpTab (ic);
13796           break;
13797             
13798         case CAST:
13799           genCast (ic);
13800           break;
13801             
13802         case RECEIVE:
13803           genReceive(ic);
13804           break;
13805             
13806         case SEND:
13807           addSet(&_G.sendSet,ic);
13808           break;
13809
13810         case DUMMY_READ_VOLATILE:
13811           genDummyRead (ic);
13812           break;
13813
13814         default :
13815           ic = ic;
13816       }
13817     }
13818
13819
13820     /* now we are ready to call the
13821        peep hole optimizer */
13822     if (!options.nopeep)
13823       peepHole (&lineHead);
13824
13825     /* now do the actual printing */
13826     printLine (lineHead, codeOutFile);
13827
13828 #ifdef PCODE_DEBUG
13829     DFPRINTF((stderr,"printing pBlock\n\n"));
13830     pic16_printpBlock(stdout,pb);
13831 #endif
13832
13833     return;
13834 }
13835