* applied a previous patch from Raphael Neider that wasn't included
[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)
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 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2f(asmop *dst, asmop *src, int offset);
61 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
62 static pCodeOp *pic16_popRegFromIdx(int rIdx);
63
64 //static int aopIdx (asmop *aop, int offset);
65
66 int pic16_labelOffset=0;
67 extern int pic16_debug_verbose;
68 static int optimized_for_speed = 0;
69 /*
70   hack hack
71
72 */
73
74 extern set *externs;
75
76 /* max_key keeps track of the largest label number used in 
77    a function. This is then used to adjust the label offset
78    for the next function.
79 */
80 static int max_key=0;
81 static int GpsuedoStkPtr=0;
82
83 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
84
85 unsigned int pic16aopLiteral (value *val, int offset);
86 const char *pic16_AopType(short type);
87 static iCode *ifxForOp ( operand *op, iCode *ic );
88
89 void pic16_pushpCodeOp(pCodeOp *pcop);
90 void pic16_poppCodeOp(pCodeOp *pcop);
91
92 static bool is_LitOp(operand *op);
93 static bool is_LitAOp(asmop *aop);
94
95
96 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
97
98 /* set the following macro to 1 to enable passing the
99  * first byte of functions parameters via WREG */
100 #define USE_WREG_IN_FUNC_PARAMS 0
101
102
103 /* this is the down and dirty file with all kinds of 
104    kludgy & hacky stuff. This is what it is all about
105    CODE GENERATION for a specific MCU . some of the
106    routines may be reusable, will have to see */
107
108 static char *zero = "#0x00";
109 static char *one  = "#0x01";
110 //static char *spname = "sp";
111
112
113 /*
114  * Function return value policy (MSB-->LSB):
115  *  8 bits      -> WREG
116  * 16 bits      -> PRODL:WREG
117  * 24 bits      -> PRODH:PRODL:WREG
118  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
119  * >32 bits     -> on stack, and FSR0 points to the beginning
120  *
121  */
122  
123
124 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
125 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
126 static char **fReturn = fReturnpic16;
127
128 static char *accUse[] = {"WREG"};
129
130 //static short rbank = -1;
131
132 static struct {
133     short r0Pushed;
134     short r1Pushed;
135     short fsr0Pushed;
136     short accInUse;
137     short inLine;
138     short debugLine;
139     short nRegsSaved;
140     short ipushRegs;
141     set *sendSet;
142     set *stackRegSet;
143     int interruptvector;
144     int usefastretfie;
145     bitVect *fregsUsed;
146     int stack_lat;                      /* stack offset latency */
147     int resDirect;
148     int useWreg;                        /* flag when WREG is used to pass function parameter */
149 } _G;
150
151 /* Resolved ifx structure. This structure stores information
152    about an iCode ifx that makes it easier to generate code.
153 */
154 typedef struct resolvedIfx {
155   symbol *lbl;     /* pointer to a label */
156   int condition;   /* true or false ifx */
157   int generated;   /* set true when the code associated with the ifx
158                     * is generated */
159 } resolvedIfx;
160
161 extern int pic16_ptrRegReq ;
162 extern int pic16_nRegs;
163 extern FILE *codeOutFile;
164 //static void saverbank (int, iCode *,bool);
165
166 static lineNode *lineHead = NULL;
167 static lineNode *lineCurr = NULL;
168
169 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
170 0xE0, 0xC0, 0x80, 0x00};
171 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
172 0x07, 0x03, 0x01, 0x00};
173
174 static  pBlock *pb;
175
176 /*-----------------------------------------------------------------*/
177 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
178 /*                 exponent of 2 is returned, otherwise -1 is      */
179 /*                 returned.                                       */
180 /* note that this is similar to the function `powof2' in SDCCsymt  */
181 /* if(n == 2^y)                                                    */
182 /*   return y;                                                     */
183 /* return -1;                                                      */
184 /*-----------------------------------------------------------------*/
185 int pic16_my_powof2 (unsigned long num)
186 {
187   if(num) {
188     if( (num & (num-1)) == 0) {
189       int nshifts = -1;
190       while(num) {
191         num>>=1;
192         nshifts++;
193       }
194       return nshifts;
195     }
196   }
197
198   return -1;
199 }
200
201 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
202 {
203   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
204                        line_no,
205                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
206                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
207                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
208                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
209                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
210                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
211                        ((result) ? AOP_SIZE(result) : 0));
212 }
213
214 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
215 {
216
217   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
218                        line_no,
219                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
220                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
221                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
222                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
223                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
224                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
225
226 }
227
228 void pic16_emitpcomment (char *fmt, ...)
229 {
230     va_list ap;
231     char lb[INITIAL_INLINEASM];  
232     char *lbp = lb;
233
234     va_start(ap,fmt);   
235
236     lb[0] = ';';
237     vsprintf(lb+1,fmt,ap);
238
239     while (isspace(*lbp)) lbp++;
240
241     if (lbp && *lbp) 
242         lineCurr = (lineCurr ?
243                     connectLine(lineCurr,newLineNode(lb)) :
244                     (lineHead = newLineNode(lb)));
245     lineCurr->isInline = _G.inLine;
246     lineCurr->isDebug  = _G.debugLine;
247
248     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
249     va_end(ap);
250
251 //      fprintf(stderr, "%s\n", lb);
252 }
253
254 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
255 {
256     va_list ap;
257     char lb[INITIAL_INLINEASM];  
258     char *lbp = lb;
259
260     if(!pic16_debug_verbose)
261       return;
262
263     va_start(ap,fmt);   
264
265     if (inst && *inst) {
266         if (fmt && *fmt)
267             sprintf(lb,"%s\t",inst);
268         else
269             sprintf(lb,"%s",inst);
270         vsprintf(lb+(strlen(lb)),fmt,ap);
271     }  else
272         vsprintf(lb,fmt,ap);
273
274     while (isspace(*lbp)) lbp++;
275
276     if (lbp && *lbp) 
277         lineCurr = (lineCurr ?
278                     connectLine(lineCurr,newLineNode(lb)) :
279                     (lineHead = newLineNode(lb)));
280     lineCurr->isInline = _G.inLine;
281     lineCurr->isDebug  = _G.debugLine;
282
283     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
284     va_end(ap);
285
286 //      fprintf(stderr, "%s\n", lb);
287 }
288
289
290
291 void pic16_emitpLabel(int key)
292 {
293   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
294 }
295
296 void pic16_emitpLabelFORCE(int key)
297 {
298   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
299 }
300
301 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
302 {
303
304   if(pcop)
305     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
306   else
307     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
308 }
309
310 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
311 {
312   if(pcop)
313     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
314   else
315     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
316 }
317   
318 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
319 {
320
321   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
322
323 }
324
325
326 #if 1
327 #define pic16_emitcode  DEBUGpic16_emitcode
328 #else
329 /*-----------------------------------------------------------------*/
330 /* pic16_emitcode - writes the code into a file : for now it is simple    */
331 /*-----------------------------------------------------------------*/
332 void pic16_emitcode (char *inst,char *fmt, ...)
333 {
334     va_list ap;
335     char lb[INITIAL_INLINEASM];  
336     char *lbp = lb;
337
338     va_start(ap,fmt);   
339
340     if (inst && *inst) {
341         if (fmt && *fmt)
342             sprintf(lb,"%s\t",inst);
343         else
344             sprintf(lb,"%s",inst);
345         vsprintf(lb+(strlen(lb)),fmt,ap);
346     }  else
347         vsprintf(lb,fmt,ap);
348
349     while (isspace(*lbp)) lbp++;
350
351     if (lbp && *lbp) 
352         lineCurr = (lineCurr ?
353                     connectLine(lineCurr,newLineNode(lb)) :
354                     (lineHead = newLineNode(lb)));
355     lineCurr->isInline = _G.inLine;
356     lineCurr->isDebug  = _G.debugLine;
357
358 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
359
360 //    if(pic16_debug_verbose)
361 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
362
363     va_end(ap);
364 }
365 #endif
366
367
368 /*-----------------------------------------------------------------*/
369 /* pic16_emitDebuggerSymbol - associate the current code location  */
370 /*   with a debugger symbol                                        */
371 /*-----------------------------------------------------------------*/
372 void
373 pic16_emitDebuggerSymbol (char * debugSym)
374 {
375   _G.debugLine = 1;
376   pic16_emitcode (";", "%s ==.", debugSym);
377   _G.debugLine = 0;
378 }
379
380
381 /*-----------------------------------------------------------------*/
382 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
383 /*-----------------------------------------------------------------*/
384 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
385 {
386 //    bool r0iu = FALSE , r1iu = FALSE;
387 //    bool r0ou = FALSE , r1ou = FALSE;
388     bool fsr0iu = FALSE, fsr0ou;
389     bool fsr2iu = FALSE, fsr2ou;
390     
391     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
392
393     
394     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
395     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
396     
397     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
398     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
399
400     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
401         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
402         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
403     }
404
405     if(!fsr0iu && !fsr0ou) {
406         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
407         (*aopp)->type = AOP_FSR0;
408
409         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
410         
411       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
412     }
413
414 #if 0
415     /* no usage of FSR2 */
416     if(!fsr2iu && !fsr2ou) {
417         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
418         (*aopp)->type = AOP_FSR2;
419
420       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
421     }
422 #endif
423         
424     /* now we know they both have usage */
425     /* if fsr0 not used in this instruction */
426     if (!fsr0iu) {
427         if (!_G.fsr0Pushed) {
428                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
429                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
430                 _G.fsr0Pushed++;
431         }
432
433         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
434         (*aopp)->type = AOP_FSR0;
435
436 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
437
438       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
439     }
440         
441
442     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
443     assert( 0 );
444
445     return NULL;
446 #if 0
447     /* the logic: if r0 & r1 used in the instruction
448     then we are in trouble otherwise */
449
450     /* first check if r0 & r1 are used by this
451     instruction, in which case we are in trouble */
452     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
453         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
454     {
455         goto endOfWorld;      
456     }
457
458     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
459     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
460
461     /* if no usage of r0 then return it */
462     if (!r0iu && !r0ou) {
463         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
464         (*aopp)->type = AOP_R0; 
465         
466         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
467     }
468
469     /* if no usage of r1 then return it */
470     if (!r1iu && !r1ou) {
471         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
472         (*aopp)->type = AOP_R1;
473
474         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
475     }    
476
477     /* now we know they both have usage */
478     /* if r0 not used in this instruction */
479     if (!r0iu) {
480         /* push it if not already pushed */
481         if (!_G.r0Pushed) {
482           //pic16_emitcode ("push","%s",
483           //          pic16_regWithIdx(R0_IDX)->dname);
484             _G.r0Pushed++ ;
485         }
486         
487         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
488         (*aopp)->type = AOP_R0;
489
490         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491     }
492
493     /* if r1 not used then */
494
495     if (!r1iu) {
496         /* push it if not already pushed */
497         if (!_G.r1Pushed) {
498           //pic16_emitcode ("push","%s",
499           //          pic16_regWithIdx(R1_IDX)->dname);
500             _G.r1Pushed++ ;
501         }
502         
503         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
504         (*aopp)->type = AOP_R1;
505         return pic16_regWithIdx(R1_IDX);
506     }
507
508 endOfWorld :
509     /* I said end of world but not quite end of world yet */
510     /* if this is a result then we can push it on the stack*/
511     if (result) {
512         (*aopp)->type = AOP_STK;    
513         return NULL;
514     }
515
516     /* other wise this is true end of the world */
517     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
518            "getFreePtr should never reach here");
519     exit(0);
520 #endif
521 }
522
523 /*-----------------------------------------------------------------*/
524 /* newAsmop - creates a new asmOp                                  */
525 /*-----------------------------------------------------------------*/
526 static asmop *newAsmop (short type)
527 {
528     asmop *aop;
529
530     aop = Safe_calloc(1,sizeof(asmop));
531     aop->type = type;
532     return aop;
533 }
534
535 static void genSetDPTR(int n)
536 {
537     if (!n)
538     {
539         pic16_emitcode(";", "Select standard DPTR");
540         pic16_emitcode("mov", "dps, #0x00");
541     }
542     else
543     {
544         pic16_emitcode(";", "Select alternate DPTR");
545         pic16_emitcode("mov", "dps, #0x01");
546     }
547 }
548
549 /*-----------------------------------------------------------------*/
550 /* resolveIfx - converts an iCode ifx into a form more useful for  */
551 /*              generating code                                    */
552 /*-----------------------------------------------------------------*/
553 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
554 {
555   FENTRY2;
556   
557 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
558
559   if(!resIfx) 
560     return;
561
562
563   resIfx->condition = 1;    /* assume that the ifx is true */
564   resIfx->generated = 0;    /* indicate that the ifx has not been used */
565
566   if(!ifx) {
567     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
568
569 #if 1
570     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
571                         __FUNCTION__,__LINE__,resIfx->lbl->key);
572 #endif
573
574   } else {
575     if(IC_TRUE(ifx)) {
576       resIfx->lbl = IC_TRUE(ifx);
577     } else {
578       resIfx->lbl = IC_FALSE(ifx);
579       resIfx->condition = 0;
580     }
581
582 #if 1
583     if(IC_TRUE(ifx)) 
584       DEBUGpic16_emitcode("; +++","ifx true is non-null");
585     else
586       DEBUGpic16_emitcode("; +++","ifx true is null");
587     if(IC_FALSE(ifx)) 
588       DEBUGpic16_emitcode("; +++","ifx false is non-null");
589     else
590       DEBUGpic16_emitcode("; +++","ifx false is null");
591 #endif
592   }
593
594   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
595
596 }
597 #if 0
598 /*-----------------------------------------------------------------*/
599 /* pointerCode - returns the code for a pointer type               */
600 /*-----------------------------------------------------------------*/
601 static int pointerCode (sym_link *etype)
602 {
603
604     return PTR_TYPE(SPEC_OCLS(etype));
605
606 }
607 #endif
608
609 /*-----------------------------------------------------------------*/
610 /* aopForSym - for a true symbol                                   */
611 /*-----------------------------------------------------------------*/
612 static asmop *aopForSym (iCode *ic, operand *op, bool result)
613 {
614     symbol *sym=OP_SYMBOL(op);
615     asmop *aop;
616     memmap *space= SPEC_OCLS(sym->etype);
617
618     FENTRY2;
619     
620     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
621     
622 //    sym = OP_SYMBOL(op);
623
624     /* if already has one */
625     if (sym->aop) {
626             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
627         return sym->aop;
628     }
629
630 #if 0
631     /* if symbol was initially placed onStack then we must re-place it
632      * to direct memory, since pic16 does not have a specific stack */
633     if(sym->onStack) {
634         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
635     }
636 #endif
637
638 #if 1
639     /* assign depending on the storage class */
640     /* if it is on the stack or indirectly addressable */
641     /* space we need to assign either r0 or r1 to it   */    
642     if (sym->onStack || sym->iaccess) {
643       pCodeOp *pcop[4];
644       int i;
645       
646         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
647                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
648         
649         /* acquire a temporary register -- it is saved in function */
650
651         sym->aop = aop = newAsmop(AOP_STA);
652         aop->aopu.stk.stk = sym->stack;
653         aop->size = getSize(sym->type);
654
655
656         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
657         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
658           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
659           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
660           
661           for(i=0;i<aop->size;i++)
662             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
663             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
664         } else
665           for(i=0;i<aop->size;i++) {
666             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
667             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
668           }
669
670
671 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
672
673 #if 1
674         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
675         
676         if(_G.accInUse) {
677                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
678         }
679         
680         for(i=0;i<aop->size;i++) {
681
682           /* initialise for stack access via frame pointer */
683           // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
684           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((sym->stack + 1 + i /*+ _G.stack_lat*/)));
685           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
686                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
687         }
688         
689         if(_G.accInUse) {
690                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
691         }
692         
693         return (aop);
694 #endif
695
696 #if 0
697         /* now assign the address of the variable to 
698         the pointer register */
699         if (aop->type != AOP_STK) {
700
701             if (sym->onStack) {
702                     if ( _G.accInUse )
703                         pic16_emitcode("push","acc");
704
705                     pic16_emitcode("mov","a,_bp");
706                     pic16_emitcode("add","a,#0x%02x",
707                              ((sym->stack < 0) ?
708                               ((char)(sym->stack - _G.nRegsSaved )) :
709                               ((char)sym->stack)) & 0xff);
710                     pic16_emitcode("mov","%s,a",
711                              aop->aopu.aop_ptr->name);
712
713                     if ( _G.accInUse )
714                         pic16_emitcode("pop","acc");
715             } else
716                 pic16_emitcode("mov","%s,#%s",
717                          aop->aopu.aop_ptr->name,
718                          sym->rname);
719             aop->paged = space->paged;
720         } else
721             aop->aopu.aop_stk = sym->stack;
722         return aop;
723 #endif
724
725     }
726 #endif
727
728 #if 0
729     if (sym->onStack && options.stack10bit)
730     {
731         /* It's on the 10 bit stack, which is located in
732          * far data space.
733          */
734          
735       //DEBUGpic16_emitcode(";","%d",__LINE__);
736
737         if ( _G.accInUse )
738                 pic16_emitcode("push","acc");
739
740         pic16_emitcode("mov","a,_bp");
741         pic16_emitcode("add","a,#0x%02x",
742                  ((sym->stack < 0) ?
743                    ((char)(sym->stack - _G.nRegsSaved )) :
744                    ((char)sym->stack)) & 0xff);
745         
746         genSetDPTR(1);
747         pic16_emitcode ("mov","dpx1,#0x40");
748         pic16_emitcode ("mov","dph1,#0x00");
749         pic16_emitcode ("mov","dpl1, a");
750         genSetDPTR(0);
751         
752         if ( _G.accInUse )
753             pic16_emitcode("pop","acc");
754             
755         sym->aop = aop = newAsmop(AOP_DPTR2);
756         aop->size = getSize(sym->type); 
757         return aop;
758     }
759 #endif
760
761 #if 0
762     /* special case for a function */
763     if (IS_FUNC(sym->type)) {   
764         sym->aop = aop = newAsmop(AOP_PCODE);
765         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
766         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
767         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
768         PCOI(aop->aopu.pcop)->index = 0;
769         aop->size = FPTRSIZE; 
770         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
771         return aop;
772     }
773 #endif
774
775
776
777     //DEBUGpic16_emitcode(";","%d",__LINE__);
778     /* if in bit space */
779     if (IN_BITSPACE(space)) {
780         sym->aop = aop = newAsmop (AOP_CRY);
781         aop->aopu.aop_dir = sym->rname ;
782         aop->size = getSize(sym->type);
783         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
784         return aop;
785     }
786     /* if it is in direct space */
787     if (IN_DIRSPACE(space)) {
788         sym->aop = aop = newAsmop (AOP_DIR);
789         aop->aopu.aop_dir = sym->rname ;
790         aop->size = getSize(sym->type);
791         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
792         pic16_allocDirReg( IC_LEFT(ic) );
793         return aop;
794     }
795
796
797     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
798         sym->aop = aop = newAsmop (AOP_DIR);
799         aop->aopu.aop_dir = sym->rname ;
800         aop->size = getSize(sym->type);
801         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
802         pic16_allocDirReg( IC_LEFT(ic) );
803         return aop;
804     }
805
806
807     /* only remaining is far space */
808     sym->aop = aop = newAsmop(AOP_PCODE);
809
810 /* change the next if to 1 to revert to good old immediate code */
811         if(IN_CODESPACE(space)) {
812                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
813                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
814                 PCOI(aop->aopu.pcop)->index = 0;
815         } else {
816                 /* try to allocate via direct register */
817                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
818 //              aop->size = getSize( sym->type );
819         }
820
821         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
822                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
823
824 #if 0
825         if(!pic16_allocDirReg (IC_LEFT(ic)))
826                 return NULL;
827 #endif
828
829         if(IN_DIRSPACE( space ))
830                 aop->size = PTRSIZE;
831         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
832                 aop->size = FPTRSIZE;
833         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
834         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
835         else if(sym->onStack) {
836                 aop->size = PTRSIZE;
837         } else {
838                 assert( 0 );
839         }
840
841     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
842
843     /* if it is in code space */
844     if (IN_CODESPACE(space))
845         aop->code = 1;
846
847     return aop;     
848 }
849
850 /*-----------------------------------------------------------------*/
851 /* aopForRemat - rematerialzes an object                           */
852 /*-----------------------------------------------------------------*/
853 static asmop *aopForRemat (operand *op) // x symbol *sym)
854 {
855   symbol *sym = OP_SYMBOL(op);
856   operand *refop;
857   iCode *ic = NULL, *oldic;
858   asmop *aop = newAsmop(AOP_PCODE);
859   int val = 0;
860   int offset = 0;
861   int viaimmd=0;
862
863     FENTRY2;
864     
865         ic = sym->rematiCode;
866
867         if(IS_OP_POINTER(op)) {
868                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
869         }
870
871         for (;;) {
872                 oldic = ic;
873
874 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
875         
876                 if (ic->op == '+') {
877                         val += (int) operandLitValue(IC_RIGHT(ic));
878                 } else if (ic->op == '-') {
879                         val -= (int) operandLitValue(IC_RIGHT(ic));
880                 } else
881                         break;
882                 
883                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
884         }
885
886         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
887         refop = IC_LEFT(ic);
888
889         if(!op->isaddr)viaimmd++; else viaimmd=0;
890                 
891 /* set the following if to 1 to revert to good old immediate code */
892         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
893                 || viaimmd) {
894
895                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
896
897                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
898
899 #if 0
900                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
901 #else
902                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
903 #endif
904
905                 PCOI(aop->aopu.pcop)->index = val;
906                 
907                 aop->size = getSize( sym->type );
908         } else {
909                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
910
911                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
912                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
913
914                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
915         }
916
917
918         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
919                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
920 #if 0
921                 val, IS_PTR_CONST(operandType(op)));
922 #else
923                 val, IS_CODEPTR(operandType(op)));
924 #endif
925
926 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
927
928         pic16_allocDirReg (IC_LEFT(ic));
929
930         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
931                 aop->code = 1;
932
933   return aop;        
934 }
935
936 #if 0
937 static int aopIdx (asmop *aop, int offset)
938 {
939   if(!aop)
940     return -1;
941
942   if(aop->type !=  AOP_REG)
943     return -2;
944         
945   return aop->aopu.aop_reg[offset]->rIdx;
946
947 }
948 #endif
949
950 /*-----------------------------------------------------------------*/
951 /* regsInCommon - two operands have some registers in common       */
952 /*-----------------------------------------------------------------*/
953 static bool regsInCommon (operand *op1, operand *op2)
954 {
955     symbol *sym1, *sym2;
956     int i;
957
958     /* if they have registers in common */
959     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
960         return FALSE ;
961
962     sym1 = OP_SYMBOL(op1);
963     sym2 = OP_SYMBOL(op2);
964
965     if (sym1->nRegs == 0 || sym2->nRegs == 0)
966         return FALSE ;
967
968     for (i = 0 ; i < sym1->nRegs ; i++) {
969         int j;
970         if (!sym1->regs[i])
971             continue ;
972
973         for (j = 0 ; j < sym2->nRegs ;j++ ) {
974             if (!sym2->regs[j])
975                 continue ;
976
977             if (sym2->regs[j] == sym1->regs[i])
978                 return TRUE ;
979         }
980     }
981
982     return FALSE ;
983 }
984
985 /*-----------------------------------------------------------------*/
986 /* operandsEqu - equivalent                                        */
987 /*-----------------------------------------------------------------*/
988 static bool operandsEqu ( operand *op1, operand *op2)
989 {
990     symbol *sym1, *sym2;
991
992     /* if they not symbols */
993     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
994         return FALSE;
995
996     sym1 = OP_SYMBOL(op1);
997     sym2 = OP_SYMBOL(op2);
998
999     /* if both are itemps & one is spilt
1000        and the other is not then false */
1001     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1002         sym1->isspilt != sym2->isspilt )
1003         return FALSE ;
1004
1005     /* if they are the same */
1006     if (sym1 == sym2)
1007         return TRUE ;
1008
1009     if (sym1->rname[0] && sym2->rname[0]
1010         && strcmp (sym1->rname, sym2->rname) == 0)
1011         return TRUE;
1012
1013
1014     /* if left is a tmp & right is not */
1015     if (IS_ITEMP(op1)  && 
1016         !IS_ITEMP(op2) &&
1017         sym1->isspilt  &&
1018         (sym1->usl.spillLoc == sym2))
1019         return TRUE;
1020
1021     if (IS_ITEMP(op2)  && 
1022         !IS_ITEMP(op1) &&
1023         sym2->isspilt  &&
1024         sym1->level > 0 &&
1025         (sym2->usl.spillLoc == sym1))
1026         return TRUE ;
1027
1028     return FALSE ;
1029 }
1030
1031 /*-----------------------------------------------------------------*/
1032 /* pic16_sameRegs - two asmops have the same registers                   */
1033 /*-----------------------------------------------------------------*/
1034 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1035 {
1036     int i;
1037
1038     if (aop1 == aop2)
1039         return TRUE ;
1040
1041     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1042                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1043
1044     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1045
1046     if (aop1->type != AOP_REG ||
1047         aop2->type != AOP_REG )
1048         return FALSE ;
1049
1050     if (aop1->size != aop2->size )
1051         return FALSE ;
1052
1053     for (i = 0 ; i < aop1->size ; i++ ) {
1054 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1055
1056 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1057         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1058             return FALSE ;
1059     }
1060
1061     return TRUE ;
1062 }
1063
1064 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1065 {
1066     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1067                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1068
1069     if(aop1 == aop2)return TRUE;
1070     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1071       
1072       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1073     
1074   return TRUE;
1075 }
1076
1077
1078 /*-----------------------------------------------------------------*/
1079 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1080 /*-----------------------------------------------------------------*/
1081 void pic16_aopOp (operand *op, iCode *ic, bool result)
1082 {
1083     asmop *aop;
1084     symbol *sym;
1085     int i;
1086
1087     if (!op)
1088         return ;
1089
1090     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1091
1092     /* if this a literal */
1093     if (IS_OP_LITERAL(op)) {
1094         op->aop = aop = newAsmop(AOP_LIT);
1095         aop->aopu.aop_lit = op->operand.valOperand;
1096         aop->size = getSize(operandType(op));
1097         return;
1098     }
1099
1100     {
1101       sym_link *type = operandType(op);
1102 #if 0
1103       if(IS_PTR_CONST(type))
1104 #else
1105       if(IS_CODEPTR(type))
1106 #endif
1107         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1108     }
1109
1110     /* if already has a asmop then continue */
1111     if (op->aop)
1112         return ;
1113
1114     /* if the underlying symbol has a aop */
1115     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1116       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1117         op->aop = OP_SYMBOL(op)->aop;
1118         return;
1119     }
1120
1121     /* if this is a true symbol */
1122     if (IS_TRUE_SYMOP(op)) {    
1123         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1124       op->aop = aopForSym(ic, op, result);
1125       return ;
1126     }
1127
1128     /* this is a temporary : this has
1129     only four choices :
1130     a) register
1131     b) spillocation
1132     c) rematerialize 
1133     d) conditional   
1134     e) can be a return use only */
1135
1136     sym = OP_SYMBOL(op);
1137
1138     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1139     /* if the type is a conditional */
1140     if (sym->regType == REG_CND) {
1141         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1142         aop->size = 0;
1143         return;
1144     }
1145
1146     /* if it is spilt then two situations
1147     a) is rematerialize 
1148     b) has a spill location */
1149     if (sym->isspilt || sym->nRegs == 0) {
1150
1151       DEBUGpic16_emitcode(";","%d",__LINE__);
1152         /* rematerialize it NOW */
1153         if (sym->remat) {
1154
1155             sym->aop = op->aop = aop = aopForRemat (op);
1156 //            aop->size = getSize(sym->type);
1157 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1158             return;
1159         }
1160
1161 #if 1
1162         if (sym->accuse) {
1163             int i;
1164             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1165             aop->size = getSize(sym->type);
1166             for ( i = 0 ; i < 1 ; i++ ) {
1167                 aop->aopu.aop_str[i] = accUse[i];
1168 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1169             }
1170             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1171             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1172             return;  
1173         }
1174 #endif
1175
1176 #if 1
1177         if (sym->ruonly ) {
1178           /*
1179           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1180           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1181           //pic16_allocDirReg (IC_LEFT(ic));
1182           aop->size = getSize(sym->type);
1183           */
1184
1185           unsigned i;
1186
1187           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1188           aop->size = getSize(sym->type);
1189           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1190             aop->aopu.aop_str[i] = fReturn[i];
1191
1192           DEBUGpic16_emitcode(";","%d",__LINE__);
1193           return;
1194         }
1195 #endif
1196         /* else spill location  */
1197         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1198             /* force a new aop if sizes differ */
1199             sym->usl.spillLoc->aop = NULL;
1200         }
1201
1202 #if 0
1203         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1204                             __FUNCTION__,__LINE__,
1205                             sym->usl.spillLoc->rname,
1206                             sym->rname, sym->usl.spillLoc->offset);
1207 #endif
1208
1209         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1210         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1211         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1212                                           getSize(sym->type), 
1213                                           sym->usl.spillLoc->offset, op);
1214         aop->size = getSize(sym->type);
1215
1216         return;
1217     }
1218
1219     {
1220       sym_link *type = operandType(op);
1221 #if 0
1222       if(IS_PTR_CONST(type)) 
1223 #else
1224       if(IS_CODEPTR(type)) 
1225 #endif
1226         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1227     }
1228
1229     /* must be in a register */
1230     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1231     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1232     aop->size = sym->nRegs;
1233     for ( i = 0 ; i < sym->nRegs ;i++)
1234         aop->aopu.aop_reg[i] = sym->regs[i];
1235 }
1236
1237 /*-----------------------------------------------------------------*/
1238 /* pic16_freeAsmop - free up the asmop given to an operand               */
1239 /*----------------------------------------------------------------*/
1240 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1241 {   
1242     asmop *aop ;
1243
1244     if (!op)
1245         aop = aaop;
1246     else 
1247         aop = op->aop;
1248
1249     if (!aop)
1250         return ;
1251
1252     if (aop->freed)
1253         goto dealloc; 
1254
1255     aop->freed = 1;
1256
1257     /* depending on the asmop type only three cases need work AOP_RO
1258        , AOP_R1 && AOP_STK */
1259 #if 1
1260     switch (aop->type) {
1261         case AOP_FSR0 :
1262             if (_G.fsr0Pushed ) {
1263                 if (pop) {
1264                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1265                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1266 //                    pic16_emitcode ("pop","ar0");
1267                     _G.fsr0Pushed--;
1268                 }
1269             }
1270             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1271             break;
1272
1273         case AOP_FSR2 :
1274             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1275             break;
1276
1277         case AOP_R0 :
1278             if (_G.r0Pushed ) {
1279                 if (pop) {
1280                     pic16_emitcode ("pop","ar0");     
1281                     _G.r0Pushed--;
1282                 }
1283             }
1284             bitVectUnSetBit(ic->rUsed,R0_IDX);
1285             break;
1286
1287         case AOP_R1 :
1288             if (_G.r1Pushed ) {
1289                 if (pop) {
1290                     pic16_emitcode ("pop","ar1");
1291                     _G.r1Pushed--;
1292                 }
1293             }
1294             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1295             break;
1296
1297         case AOP_STA:
1298           {
1299             int i;
1300
1301               /* we must store the result on stack */
1302               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1303                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1304                 for(i=0;i<aop->size;i++) {
1305                   /* initialise for stack access via frame pointer */
1306                   // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
1307                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit((OP_SYMBOL(IC_RESULT(ic))->stack + 1 + i /*+ _G.stack_lat*/)));
1308                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1309                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1310                 }
1311         
1312                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1313               }
1314
1315               if(!_G.resDirect) {
1316                 for(i=0;i<aop->size;i++)
1317                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1318               }
1319               _G.resDirect = 0;
1320           }
1321           break;
1322 #if 0
1323         case AOP_STK :
1324         {
1325             int sz = aop->size;    
1326             int stk = aop->aopu.aop_stk + aop->size;
1327             bitVectUnSetBit(ic->rUsed,R0_IDX);
1328             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1329
1330             getFreePtr(ic,&aop,FALSE);
1331             
1332             if (options.stack10bit)
1333             {
1334                 /* I'm not sure what to do here yet... */
1335                 /* #STUB */
1336                 fprintf(stderr, 
1337                         "*** Warning: probably generating bad code for "
1338                         "10 bit stack mode.\n");
1339             }
1340             
1341             if (stk) {
1342                 pic16_emitcode ("mov","a,_bp");
1343                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1344                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1345             } else {
1346                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1347             }
1348
1349             while (sz--) {
1350                 pic16_emitcode("pop","acc");
1351                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1352                 if (!sz) break;
1353                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1354             }
1355             op->aop = aop;
1356             pic16_freeAsmop(op,NULL,ic,TRUE);
1357             if (_G.r0Pushed) {
1358                 pic16_emitcode("pop","ar0");
1359                 _G.r0Pushed--;
1360             }
1361
1362             if (_G.r1Pushed) {
1363                 pic16_emitcode("pop","ar1");
1364                 _G.r1Pushed--;
1365             }       
1366         }
1367 #endif
1368
1369     }
1370 #endif
1371
1372 dealloc:
1373     /* all other cases just dealloc */
1374     if (op ) {
1375         op->aop = NULL;
1376         if (IS_SYMOP(op)) {
1377             OP_SYMBOL(op)->aop = NULL;    
1378             /* if the symbol has a spill */
1379             if (SPIL_LOC(op))
1380                 SPIL_LOC(op)->aop = NULL;
1381         }
1382     }
1383 }
1384
1385 /*-----------------------------------------------------------------*/
1386 /* pic16_aopGet - for fetching value of the aop                          */
1387 /*-----------------------------------------------------------------*/
1388 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1389 {
1390     char *s = buffer ;
1391     char *rs;
1392
1393     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1394
1395     /* offset is greater than size then zero */
1396     if (offset > (aop->size - 1) &&
1397         aop->type != AOP_LIT)
1398         return zero;
1399
1400     /* depending on type */
1401     switch (aop->type) {
1402
1403     case AOP_FSR0:
1404     case AOP_FSR2:
1405       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1406       rs = Safe_calloc(1, strlen(s)+1);
1407       strcpy(rs, s);
1408       return (rs);
1409       
1410 #if 0
1411       /* if we need to increment it */
1412       while (offset > aop->coff)
1413         {
1414           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1415           aop->coff++;
1416         }
1417
1418       while (offset < aop->coff)
1419         {
1420           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1421           aop->coff--;
1422         }
1423       aop->coff = offset;
1424       if (aop->paged)
1425         {
1426           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1427           return (dname ? "acc" : "a");
1428         }
1429       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1430       rs = Safe_calloc (1, strlen (s) + 1);
1431       strcpy (rs, s);
1432       return rs;
1433 #endif
1434
1435         
1436     case AOP_IMMD:
1437         if (bit16) 
1438             sprintf (s,"%s",aop->aopu.aop_immd);
1439         else
1440             if (offset) 
1441                 sprintf(s,"(%s >> %d)",
1442                         aop->aopu.aop_immd,
1443                         offset*8);
1444             else
1445                 sprintf(s,"%s",
1446                         aop->aopu.aop_immd);
1447         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1448         rs = Safe_calloc(1,strlen(s)+1);
1449         strcpy(rs,s);   
1450         return rs;
1451         
1452     case AOP_DIR:
1453       if (offset) {
1454         sprintf(s,"(%s + %d)",
1455                 aop->aopu.aop_dir,
1456                 offset);
1457         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1458       } else
1459             sprintf(s,"%s",aop->aopu.aop_dir);
1460         rs = Safe_calloc(1,strlen(s)+1);
1461         strcpy(rs,s);   
1462         return rs;
1463         
1464     case AOP_REG:
1465       //if (dname) 
1466       //    return aop->aopu.aop_reg[offset]->dname;
1467       //else
1468             return aop->aopu.aop_reg[offset]->name;
1469         
1470     case AOP_CRY:
1471       //pic16_emitcode(";","%d",__LINE__);
1472       return aop->aopu.aop_dir;
1473         
1474     case AOP_ACC:
1475         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1476 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1477 //        assert( 0 );
1478 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1479         rs = Safe_strdup("WREG");
1480         return (rs);
1481
1482     case AOP_LIT:
1483         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1484         rs = Safe_calloc(1,strlen(s)+1);
1485         strcpy(rs,s);   
1486         return rs;
1487         
1488     case AOP_STR:
1489         aop->coff = offset ;
1490         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1491             dname)
1492             return "acc";
1493         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1494         
1495         return aop->aopu.aop_str[offset];
1496         
1497     case AOP_PCODE:
1498       {
1499         pCodeOp *pcop = aop->aopu.pcop;
1500         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1501         if(pcop->name) {
1502           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1503           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1504           if (offset) {
1505             pic16_emitpcomment ("; =!= %s:%d: changed from %s to (%s + %d)", __FUNCTION__, __LINE__, pcop->name, pcop->name, offset);
1506             sprintf(s,"(%s + %d)", pcop->name, offset);
1507           } else {
1508             sprintf(s,"%s", pcop->name);
1509           }
1510         } else
1511           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1512
1513       }
1514       rs = Safe_calloc(1,strlen(s)+1);
1515       strcpy(rs,s);   
1516       return rs;
1517
1518     case AOP_STA:
1519         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1520         return (rs);
1521         
1522     case AOP_STK:
1523 //        pCodeOp *pcop = aop->aop
1524         break;
1525
1526     }
1527
1528     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1529     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1530            "aopget got unsupported aop->type");
1531     exit(0);
1532 }
1533
1534
1535
1536 /* lock has the following meaning: When allocating temporary registers
1537  * for stack variables storage, the value of the temporary register is
1538  * saved on stack. Its value is restored at the end. This procedure is
1539  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1540  * a possibility that before a call to pic16_aopOp, a temporary register
1541  * is allocated for a while and it is freed after some time, this will
1542  * mess the stack and values will not be restored properly. So use lock=1
1543  * to allocate temporary registers used internally by the programmer, and
1544  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1545  * to inform the compiler developer about a possible bug. This is an internal
1546  * feature for developing the compiler -- VR */
1547  
1548 int _TempReg_lock = 0;
1549 /*-----------------------------------------------------------------*/
1550 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1551 /*-----------------------------------------------------------------*/
1552 pCodeOp *pic16_popGetTempReg(int lock)
1553 {
1554   pCodeOp *pcop;
1555   symbol *cfunc;
1556
1557 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1558     if(_TempReg_lock) {
1559 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1560     }
1561     
1562     _TempReg_lock += lock;
1563     
1564     cfunc = currFunc;
1565     currFunc = NULL;
1566
1567     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1568     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1569       PCOR(pcop)->r->wasUsed=1;
1570       PCOR(pcop)->r->isFree=0;
1571
1572       /* push value on stack */
1573       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1574     }
1575
1576     currFunc = cfunc;
1577
1578   return pcop;
1579 }
1580
1581 /*-----------------------------------------------------------------*/
1582 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1583 /*                            don't save if inside v               */
1584 /*-----------------------------------------------------------------*/
1585 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1586 {
1587   pCodeOp *pcop;
1588   symbol *cfunc;
1589
1590 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1591
1592     if(_TempReg_lock) {
1593 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1594     }
1595
1596     _TempReg_lock += lock;
1597
1598     cfunc = currFunc;
1599     currFunc = NULL;
1600
1601     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1602     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1603       PCOR(pcop)->r->wasUsed=1;
1604       PCOR(pcop)->r->isFree=0;
1605
1606       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1607       /* push value on stack */
1608         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1609       }
1610     }
1611
1612     currFunc = cfunc;
1613
1614   return pcop;
1615 }
1616
1617
1618 /*-----------------------------------------------------------------*/
1619 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1620 /*-----------------------------------------------------------------*/
1621 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1622 {
1623   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1624
1625   _TempReg_lock -= lock;
1626
1627   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1628     PCOR(pcop)->r->isFree = 1;
1629     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1630   }
1631 }
1632 /*-----------------------------------------------------------------*/
1633 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1634 /*-----------------------------------------------------------------*/
1635 pCodeOp *pic16_popGetLabel(unsigned int key)
1636 {
1637
1638   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1639
1640   if(key>max_key)
1641     max_key = key;
1642
1643   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1644 }
1645
1646 /*-----------------------------------------------------------------*/
1647 /* pic16_popCopyReg - copy a pcode operator                              */
1648 /*-----------------------------------------------------------------*/
1649 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1650 {
1651   pCodeOpReg *pcor;
1652
1653   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1654   pcor->pcop.type = pc->pcop.type;
1655   if(pc->pcop.name) {
1656     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1657       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1658   } else
1659     pcor->pcop.name = NULL;
1660
1661   pcor->r = pc->r;
1662   pcor->rIdx = pc->rIdx;
1663   pcor->r->wasUsed=1;
1664   pcor->instance = pc->instance;
1665
1666 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1667
1668   return PCOP(pcor);
1669 }
1670
1671 /*-----------------------------------------------------------------*/
1672 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1673 /*-----------------------------------------------------------------*/
1674 pCodeOp *pic16_popGetLit(int lit)
1675 {
1676   return pic16_newpCodeOpLit(lit);
1677 }
1678
1679 /*-----------------------------------------------------------------*/
1680 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1683 {
1684   return pic16_newpCodeOpLit2(lit, arg2);
1685 }
1686
1687
1688 /*-----------------------------------------------------------------*/
1689 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1690 /*-----------------------------------------------------------------*/
1691 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1692 {
1693   return pic16_newpCodeOpImmd(name, offset,index, 0);
1694 }
1695
1696
1697 /*-----------------------------------------------------------------*/
1698 /* pic16_popGet - asm operator to pcode operator conversion              */
1699 /*-----------------------------------------------------------------*/
1700 pCodeOp *pic16_popGetWithString(char *str)
1701 {
1702   pCodeOp *pcop;
1703
1704
1705   if(!str) {
1706     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1707     exit (1);
1708   }
1709
1710   pcop = pic16_newpCodeOp(str,PO_STR);
1711
1712   return pcop;
1713 }
1714
1715 /*-----------------------------------------------------------------*/
1716 /* pic16_popRegFromString -                                        */
1717 /*-----------------------------------------------------------------*/
1718 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1719 {
1720
1721   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1722   pcop->type = PO_DIR;
1723
1724   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1725   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1726
1727   if(!str)
1728     str = "BAD_STRING";
1729
1730   pcop->name = Safe_calloc(1,strlen(str)+1);
1731   strcpy(pcop->name,str);
1732
1733   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1734
1735   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1736
1737   /* make sure that register doesn't exist,
1738    * and operand isn't NULL
1739    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1740   if((PCOR(pcop)->r == NULL) 
1741     && (op)
1742     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1743 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1744 //              __FUNCTION__, __LINE__, str, size, offset);
1745
1746     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1747     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1748
1749   }
1750   PCOR(pcop)->instance = offset;
1751
1752   return pcop;
1753 }
1754
1755 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1756 {
1757   pCodeOp *pcop;
1758
1759 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1760
1761         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1762         PCOR(pcop)->rIdx = rIdx;
1763         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1764
1765         PCOR(pcop)->r->isFree = 0;
1766         PCOR(pcop)->r->wasUsed = 1;
1767
1768         pcop->type = PCOR(pcop)->r->pc_type;
1769
1770   return pcop;
1771 }
1772
1773 /*---------------------------------------------------------------------------------*/
1774 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1775 /*                 VR 030601                                                       */
1776 /*---------------------------------------------------------------------------------*/
1777 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1778 {
1779   pCodeOpReg2 *pcop2;
1780   pCodeOp *temp;
1781   
1782         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1783
1784         /* comment the following check, so errors to throw up */
1785 //      if(!pcop2)return NULL;
1786
1787         temp = pic16_popGet(aop_dst, offset);
1788         pcop2->pcop2 = temp;
1789         
1790   return PCOP(pcop2);
1791 }
1792
1793
1794
1795 /*--------------------------------------------------------------------------------.-*/
1796 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1797 /*                  VR 030601 , adapted by Hans Dorn                                */
1798 /*--------------------------------------------------------------------------------.-*/
1799 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1800 {
1801   pCodeOpReg2 *pcop2;
1802  
1803         pcop2 = (pCodeOpReg2 *)src;
1804         pcop2->pcop2 = dst;
1805         
1806         return PCOP(pcop2);
1807 }
1808
1809
1810
1811 /*---------------------------------------------------------------------------------*/
1812 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1813 /*                     movff instruction                                           */
1814 /*---------------------------------------------------------------------------------*/
1815 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1816 {
1817   pCodeOpReg2 *pcop2;
1818
1819         if(!noalloc) {
1820                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1821                 pcop2->pcop2 = pic16_popCopyReg(dst);
1822         } else {
1823                 /* the pCodeOp may be already allocated */
1824                 pcop2 = (pCodeOpReg2 *)(src);
1825                 pcop2->pcop2 = (pCodeOp *)(dst);
1826         }
1827
1828   return PCOP(pcop2);
1829 }
1830
1831
1832 /*-----------------------------------------------------------------*/
1833 /* pic16_popGet - asm operator to pcode operator conversion              */
1834 /*-----------------------------------------------------------------*/
1835 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1836 {
1837   //char *s = buffer ;
1838   char *rs;
1839   pCodeOp *pcop;
1840
1841     FENTRY2;
1842     /* offset is greater than
1843     size then zero */
1844
1845 //    if (offset > (aop->size - 1) &&
1846 //        aop->type != AOP_LIT)
1847 //      return NULL;  //zero;
1848
1849     /* depending on type */
1850     switch (aop->type) {
1851         
1852     case AOP_R0:
1853     case AOP_R1:
1854     case AOP_DPTR:
1855     case AOP_DPTR2:
1856         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1857         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1858         assert( 0 );
1859         return NULL;
1860
1861
1862     case AOP_FSR0:
1863     case AOP_FSR2:
1864       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1865       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1866       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1867       PCOR(pcop)->r->wasUsed = 1;
1868       PCOR(pcop)->r->isFree = 0;
1869       
1870       PCOR(pcop)->instance = offset;
1871       pcop->type = PCOR(pcop)->r->pc_type;
1872       return (pcop);
1873
1874     case AOP_IMMD:
1875       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1876       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1877
1878     case AOP_STA:
1879       /* pCodeOp is already allocated from aopForSym */
1880         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1881         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1882           
1883       return (pcop);
1884       
1885     case AOP_ACC:
1886       {
1887         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1888
1889         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1890
1891         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1892         
1893         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1894         PCOR(pcop)->rIdx = rIdx;
1895         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1896         PCOR(pcop)->r->wasUsed=1;
1897         PCOR(pcop)->r->isFree=0;
1898
1899         PCOR(pcop)->instance = offset;
1900         pcop->type = PCOR(pcop)->r->pc_type;
1901 //      rs = aop->aopu.aop_reg[offset]->name;
1902 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1903         return pcop;
1904
1905
1906 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1907 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1908
1909 //      assert( 0 );
1910       }
1911         
1912     case AOP_DIR:
1913       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1914       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1915         
1916     case AOP_REG:
1917       {
1918         int rIdx;
1919         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1920         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1921
1922         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1923         
1924         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1925 //      pcop->type = PO_GPR_REGISTER;
1926         PCOR(pcop)->rIdx = rIdx;
1927         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1928         PCOR(pcop)->r->wasUsed=1;
1929         PCOR(pcop)->r->isFree=0;
1930
1931         PCOR(pcop)->instance = offset;
1932         pcop->type = PCOR(pcop)->r->pc_type;
1933         
1934         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1935         rs = aop->aopu.aop_reg[offset]->name;
1936         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1937         return pcop;
1938       }
1939
1940     case AOP_CRY:
1941         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1942
1943       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1944       PCOR(pcop)->instance = offset;
1945       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1946       //if(PCOR(pcop)->r == NULL)
1947       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1948       return pcop;
1949         
1950     case AOP_LIT:
1951         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1952       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1953
1954     case AOP_STR:
1955       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1956       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1957
1958       /*
1959       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1960       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1961       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1962       pcop->type = PCOR(pcop)->r->pc_type;
1963       pcop->name = PCOR(pcop)->r->name;
1964
1965       return pcop;
1966       */
1967
1968     case AOP_PCODE:
1969       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1970                           __LINE__, 
1971                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1972       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1973 #if 1
1974         switch( aop->aopu.pcop->type ) {
1975                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1976                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1977                 default:
1978                         assert( 0 );    /* should never reach here */;
1979         }
1980 #else
1981       PCOI(pcop)->offset = offset;
1982 #endif
1983       return pcop;
1984     }
1985
1986     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1987            "pic16_popGet got unsupported aop->type");
1988     exit(0);
1989 }
1990 /*-----------------------------------------------------------------*/
1991 /* pic16_aopPut - puts a string for a aop                                */
1992 /*-----------------------------------------------------------------*/
1993 void pic16_aopPut (asmop *aop, char *s, int offset)
1994 {
1995     char *d = buffer ;
1996     symbol *lbl ;
1997
1998     return;
1999
2000     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2001
2002     if (aop->size && offset > ( aop->size - 1)) {
2003         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2004                "pic16_aopPut got offset > aop->size");
2005         exit(0);
2006     }
2007
2008     /* will assign value to value */
2009     /* depending on where it is ofcourse */
2010     switch (aop->type) {
2011     case AOP_DIR:
2012       if (offset) {
2013         sprintf(d,"(%s + %d)",
2014                 aop->aopu.aop_dir,offset);
2015         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2016
2017       } else
2018             sprintf(d,"%s",aop->aopu.aop_dir);
2019         
2020         if (strcmp(d,s)) {
2021           DEBUGpic16_emitcode(";","%d",__LINE__);
2022           if(strcmp(s,"W"))
2023             pic16_emitcode("movf","%s,w",s);
2024           pic16_emitcode("movwf","%s",d);
2025
2026           if(strcmp(s,"W")) {
2027             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2028             if(offset >= aop->size) {
2029               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2030               break;
2031             } else
2032               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2033           }
2034
2035           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2036
2037
2038         }
2039         break;
2040         
2041     case AOP_REG:
2042       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2043         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2044           /*
2045             if (*s == '@'           ||
2046                 strcmp(s,"r0") == 0 ||
2047                 strcmp(s,"r1") == 0 ||
2048                 strcmp(s,"r2") == 0 ||
2049                 strcmp(s,"r3") == 0 ||
2050                 strcmp(s,"r4") == 0 ||
2051                 strcmp(s,"r5") == 0 ||
2052                 strcmp(s,"r6") == 0 || 
2053                 strcmp(s,"r7") == 0 )
2054                 pic16_emitcode("mov","%s,%s  ; %d",
2055                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2056             else
2057           */
2058
2059           if(strcmp(s,"W")==0 )
2060             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2061
2062           pic16_emitcode("movwf","%s",
2063                    aop->aopu.aop_reg[offset]->name);
2064
2065           if(strcmp(s,zero)==0) {
2066             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2067
2068           } else if(strcmp(s,"W")==0) {
2069             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2070             pcop->type = PO_GPR_REGISTER;
2071
2072             PCOR(pcop)->rIdx = -1;
2073             PCOR(pcop)->r = NULL;
2074
2075             DEBUGpic16_emitcode(";","%d",__LINE__);
2076             pcop->name = Safe_strdup(s);
2077             pic16_emitpcode(POC_MOVFW,pcop);
2078             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2079           } else if(strcmp(s,one)==0) {
2080             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2081             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2082           } else {
2083             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2084           }
2085         }
2086         break;
2087         
2088     case AOP_DPTR:
2089     case AOP_DPTR2:
2090     
2091     if (aop->type == AOP_DPTR2)
2092     {
2093         genSetDPTR(1);
2094     }
2095     
2096         if (aop->code) {
2097             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2098                    "pic16_aopPut writting to code space");
2099             exit(0);
2100         }
2101         
2102         while (offset > aop->coff) {
2103             aop->coff++;
2104             pic16_emitcode ("inc","dptr");
2105         }
2106         
2107         while (offset < aop->coff) {
2108             aop->coff-- ;
2109             pic16_emitcode("lcall","__decdptr");
2110         }
2111         
2112         aop->coff = offset;
2113         
2114         /* if not in accumulater */
2115         MOVA(s);        
2116         
2117         pic16_emitcode ("movx","@dptr,a");
2118         
2119     if (aop->type == AOP_DPTR2)
2120     {
2121         genSetDPTR(0);
2122     }
2123         break;
2124         
2125     case AOP_R0:
2126     case AOP_R1:
2127         while (offset > aop->coff) {
2128             aop->coff++;
2129             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2130         }
2131         while (offset < aop->coff) {
2132             aop->coff-- ;
2133             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2134         }
2135         aop->coff = offset;
2136         
2137         if (aop->paged) {
2138             MOVA(s);           
2139             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2140             
2141         } else
2142             if (*s == '@') {
2143                 MOVA(s);
2144                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2145             } else
2146                 if (strcmp(s,"r0") == 0 ||
2147                     strcmp(s,"r1") == 0 ||
2148                     strcmp(s,"r2") == 0 ||
2149                     strcmp(s,"r3") == 0 ||
2150                     strcmp(s,"r4") == 0 ||
2151                     strcmp(s,"r5") == 0 ||
2152                     strcmp(s,"r6") == 0 || 
2153                     strcmp(s,"r7") == 0 ) {
2154                     char buffer[10];
2155                     sprintf(buffer,"a%s",s);
2156                     pic16_emitcode("mov","@%s,%s",
2157                              aop->aopu.aop_ptr->name,buffer);
2158                 } else
2159                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2160         
2161         break;
2162         
2163     case AOP_STK:
2164         if (strcmp(s,"a") == 0)
2165             pic16_emitcode("push","acc");
2166         else
2167             pic16_emitcode("push","%s",s);
2168         
2169         break;
2170         
2171     case AOP_CRY:
2172         /* if bit variable */
2173         if (!aop->aopu.aop_dir) {
2174             pic16_emitcode("clr","a");
2175             pic16_emitcode("rlc","a");
2176         } else {
2177             if (s == zero) 
2178                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2179             else
2180                 if (s == one)
2181                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2182                 else
2183                     if (!strcmp(s,"c"))
2184                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2185                     else {
2186                         lbl = newiTempLabel(NULL);
2187                         
2188                         if (strcmp(s,"a")) {
2189                             MOVA(s);
2190                         }
2191                         pic16_emitcode("clr","c");
2192                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2193                         pic16_emitcode("cpl","c");
2194                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2195                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2196                     }
2197         }
2198         break;
2199         
2200     case AOP_STR:
2201         aop->coff = offset;
2202         if (strcmp(aop->aopu.aop_str[offset],s))
2203             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2204         break;
2205         
2206     case AOP_ACC:
2207         aop->coff = offset;
2208         if (!offset && (strcmp(s,"acc") == 0))
2209             break;
2210         
2211         if (strcmp(aop->aopu.aop_str[offset],s))
2212             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2213         break;
2214
2215     default :
2216         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2217 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2218 //             "pic16_aopPut got unsupported aop->type");
2219 //      exit(0);    
2220     }    
2221
2222 }
2223
2224 /*-----------------------------------------------------------------*/
2225 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2226 /*-----------------------------------------------------------------*/
2227 void pic16_mov2w (asmop *aop, int offset)
2228 {
2229   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2230
2231   if(is_LitAOp(aop))
2232     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2233   else
2234     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2235 }
2236
2237 static void mov2f(asmop *dst, asmop *src, int offset)
2238 {
2239   if(is_LitAOp(src)) {
2240     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2241     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2242   } else {
2243     if(pic16_sameRegsOfs(src, dst, offset))return;
2244     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2245                       pic16_popGet(dst, offset)));
2246   }
2247 }
2248
2249 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2250 {
2251   if(is_LitAOp(src)) {
2252     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2253     pic16_emitpcode(POC_MOVWF, dst);
2254   } else {
2255     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2256   }
2257 }
2258
2259 void pic16_testStackOverflow(void)
2260 {
2261 #define GSTACK_TEST_NAME        "__gstack_test"
2262
2263   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2264   
2265   {
2266     symbol *sym;
2267
2268       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2269       strcpy(sym->rname, GSTACK_TEST_NAME);
2270       checkAddSym(&externs, sym);
2271   }
2272
2273 }
2274
2275 /* push pcop into stack */
2276 void pic16_pushpCodeOp(pCodeOp *pcop)
2277 {
2278 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2279   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2280   if(pic16_options.gstack)
2281     pic16_testStackOverflow();
2282     
2283 }
2284
2285 /* pop pcop from stack */
2286 void pic16_poppCodeOp(pCodeOp *pcop)
2287 {
2288   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2289   if(pic16_options.gstack)
2290     pic16_testStackOverflow();
2291 }
2292
2293
2294 /*-----------------------------------------------------------------*/
2295 /* pushw - pushes wreg to stack                                    */
2296 /*-----------------------------------------------------------------*/
2297 void pushw(void)
2298 {
2299   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2300   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2301   if(pic16_options.gstack)
2302     pic16_testStackOverflow();
2303 }
2304
2305                 
2306 /*-----------------------------------------------------------------*/
2307 /* pushaop - pushes aop to stack                                   */
2308 /*-----------------------------------------------------------------*/
2309 void pushaop(asmop *aop, int offset)
2310 {
2311   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2312
2313   if(is_LitAOp(aop)) {
2314     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2315     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2316   } else {
2317     pic16_emitpcode(POC_MOVFF,
2318       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2319   }
2320
2321 //  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2322   if(pic16_options.gstack)
2323     pic16_testStackOverflow();
2324 }
2325
2326 /*-----------------------------------------------------------------*/
2327 /* popaop - pops aop from stack                                    */
2328 /*-----------------------------------------------------------------*/
2329 void popaop(asmop *aop, int offset)
2330 {
2331   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2332   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2333   if(pic16_options.gstack)
2334     pic16_testStackOverflow();
2335 }
2336
2337 void popaopidx(asmop *aop, int offset, int index)
2338 {
2339   int ofs=1;
2340
2341     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2342
2343     if(STACK_MODEL_LARGE)ofs++;
2344
2345     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2346     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2347     if(pic16_options.gstack)
2348       pic16_testStackOverflow();
2349 }
2350
2351 /*-----------------------------------------------------------------*/
2352 /* reAdjustPreg - points a register back to where it should        */
2353 /*-----------------------------------------------------------------*/
2354 static void reAdjustPreg (asmop *aop)
2355 {
2356     int size ;
2357
2358     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2359     aop->coff = 0;
2360     if ((size = aop->size) <= 1)
2361         return ;
2362     size-- ;
2363     switch (aop->type) {
2364         case AOP_R0 :
2365         case AOP_R1 :
2366             while (size--)
2367                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2368             break;          
2369         case AOP_DPTR :
2370         case AOP_DPTR2:
2371             if (aop->type == AOP_DPTR2)
2372             {
2373                 genSetDPTR(1);
2374             } 
2375             while (size--)
2376             {
2377                 pic16_emitcode("lcall","__decdptr");
2378             }
2379                 
2380             if (aop->type == AOP_DPTR2)
2381             {
2382                 genSetDPTR(0);
2383             }                
2384             break;  
2385
2386     }   
2387
2388 }
2389
2390
2391 #if 0
2392 /*-----------------------------------------------------------------*/
2393 /* opIsGptr: returns non-zero if the passed operand is             */   
2394 /* a generic pointer type.                                         */
2395 /*-----------------------------------------------------------------*/ 
2396 static int opIsGptr(operand *op)
2397 {
2398     sym_link *type = operandType(op);
2399     
2400     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2401     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2402     {
2403         return 1;
2404     }
2405     return 0;        
2406 }
2407 #endif
2408
2409 /*-----------------------------------------------------------------*/
2410 /* pic16_getDataSize - get the operand data size                         */
2411 /*-----------------------------------------------------------------*/
2412 int pic16_getDataSize(operand *op)
2413 {
2414     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2415
2416
2417     return AOP_SIZE(op);
2418
2419     // tsd- in the pic port, the genptr size is 1, so this code here
2420     // fails. ( in the 8051 port, the size was 4).
2421 #if 0
2422     int size;
2423     size = AOP_SIZE(op);
2424     if (size == GPTRSIZE)
2425     {
2426         sym_link *type = operandType(op);
2427         if (IS_GENPTR(type))
2428         {
2429             /* generic pointer; arithmetic operations
2430              * should ignore the high byte (pointer type).
2431              */
2432             size--;
2433     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2434         }
2435     }
2436     return size;
2437 #endif
2438 }
2439
2440 /*-----------------------------------------------------------------*/
2441 /* pic16_outAcc - output Acc                                             */
2442 /*-----------------------------------------------------------------*/
2443 void pic16_outAcc(operand *result)
2444 {
2445   int size,offset;
2446   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2447   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2448
2449
2450   size = pic16_getDataSize(result);
2451   if(size){
2452     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2453     size--;
2454     offset = 1;
2455     /* unsigned or positive */
2456     while(size--)
2457       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2458   }
2459
2460 }
2461
2462 /*-----------------------------------------------------------------*/
2463 /* pic16_outBitC - output a bit C                                  */
2464 /*                 Move to result the value of Carry flag -- VR    */
2465 /*-----------------------------------------------------------------*/
2466 void pic16_outBitC(operand *result)
2467 {
2468   int i;
2469
2470     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2471
2472     /* if the result is bit */
2473     if (AOP_TYPE(result) == AOP_CRY) {
2474         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2475         pic16_aopPut(AOP(result),"c",0);
2476     } else {
2477
2478         i = AOP_SIZE(result);
2479         while(i--) {
2480                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2481         }
2482         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2483     }
2484 }
2485
2486 /*-----------------------------------------------------------------*/
2487 /* pic16_outBitOp - output a bit from Op                           */
2488 /*                 Move to result the value of set/clr op -- VR    */
2489 /*-----------------------------------------------------------------*/
2490 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2491 {
2492   int i;
2493
2494     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2495
2496     /* if the result is bit */
2497     if (AOP_TYPE(result) == AOP_CRY) {
2498         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2499         pic16_aopPut(AOP(result),"c",0);
2500     } else {
2501
2502         i = AOP_SIZE(result);
2503         while(i--) {
2504                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2505         }
2506         pic16_emitpcode(POC_RRCF, pcop);          
2507         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2508     }
2509 }
2510
2511 /*-----------------------------------------------------------------*/
2512 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2513 /*-----------------------------------------------------------------*/
2514 void pic16_toBoolean(operand *oper)
2515 {
2516     int size = AOP_SIZE(oper) - 1;
2517     int offset = 1;
2518
2519     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2520
2521     if ( AOP_TYPE(oper) != AOP_ACC) {
2522       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2523     }
2524     while (size--) {
2525       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2526     }
2527 }
2528
2529
2530 #if !defined(GEN_Not)
2531 /*-----------------------------------------------------------------*/
2532 /* genNot - generate code for ! operation                          */
2533 /*-----------------------------------------------------------------*/
2534 static void pic16_genNot (iCode *ic)
2535 {
2536   symbol *tlbl;
2537   int size;
2538
2539   FENTRY;
2540   /* assign asmOps to operand & result */
2541   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2542   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2543
2544   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2545   /* if in bit space then a special case */
2546   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2547     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2548       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2549       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2550     } else {
2551       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2552       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2553       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2554     }
2555     goto release;
2556   }
2557
2558   size = AOP_SIZE(IC_LEFT(ic));
2559   if(size == 1) {
2560     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2561     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2562     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2563     goto release;
2564   }
2565   pic16_toBoolean(IC_LEFT(ic));
2566
2567   tlbl = newiTempLabel(NULL);
2568   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2569   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2570   pic16_outBitC(IC_RESULT(ic));
2571
2572  release:    
2573   /* release the aops */
2574   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2575   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2576 }
2577 #endif
2578
2579
2580 #if !defined(GEN_Cpl)
2581 /*-----------------------------------------------------------------*/
2582 /* genCpl - generate code for complement                           */
2583 /*-----------------------------------------------------------------*/
2584 static void pic16_genCpl (iCode *ic)
2585 {
2586   int offset = 0;
2587   int size ;
2588
2589     FENTRY;
2590     /* assign asmOps to operand & result */
2591     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2592     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2593
2594     /* if both are in bit space then 
2595     a special case */
2596     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2597         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2598
2599         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2600         pic16_emitcode("cpl","c"); 
2601         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2602         goto release; 
2603     } 
2604
2605     size = AOP_SIZE(IC_RESULT(ic));
2606     while (size--) {
2607 /*
2608         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2609         MOVA(l);       
2610         pic16_emitcode("cpl","a");
2611         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2612 */
2613         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2614               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2615         } else {
2616                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2617                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2618         }
2619         offset++;
2620
2621     }
2622
2623
2624 release:
2625     /* release the aops */
2626     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2627     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2628 }
2629 #endif
2630
2631 /*-----------------------------------------------------------------*/
2632 /* genUminusFloat - unary minus for floating points                */
2633 /*-----------------------------------------------------------------*/
2634 static void genUminusFloat(operand *op,operand *result)
2635 {
2636   int size ,offset =0 ;
2637   
2638     FENTRY;
2639     /* for this we just need to flip the 
2640     first it then copy the rest in place */
2641     size = AOP_SIZE(op);
2642
2643     while(size--) {
2644       mov2f(AOP(result), AOP(op), offset);
2645       offset++;
2646     }
2647     
2648     /* toggle the MSB's highest bit */
2649     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2650 }
2651
2652 /*-----------------------------------------------------------------*/
2653 /* genUminus - unary minus code generation                         */
2654 /*-----------------------------------------------------------------*/
2655 static void genUminus (iCode *ic)
2656 {
2657   int size, i;
2658   sym_link *optype, *rtype;
2659
2660     FENTRY;     
2661     
2662     /* assign asmops */
2663     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2664     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2665
2666     /* if both in bit space then special case */
2667     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2668       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2669         
2670         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2671         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2672         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2673         goto release; 
2674     } 
2675
2676     optype = operandType(IC_LEFT(ic));
2677     rtype = operandType(IC_RESULT(ic));
2678
2679     /* if float then do float stuff */
2680     if (IS_FLOAT(optype)) {
2681       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2682       goto release;
2683     }
2684
2685     /* otherwise subtract from zero by taking the 2's complement */
2686     size = AOP_SIZE(IC_LEFT(ic));
2687
2688     for(i=0; i<size; i++) {
2689       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2690         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2691       else {
2692         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2693         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2694       }
2695     }
2696
2697     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2698     for(i=1; i<size; i++) {
2699       emitSKPNZ;
2700       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2701     }
2702
2703 release:
2704     /* release the aops */
2705     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2706     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2707 }
2708
2709 #if 0
2710 /*-----------------------------------------------------------------*/
2711 /* saveRegisters - will look for a call and save the registers     */
2712 /*-----------------------------------------------------------------*/
2713 static void saveRegisters(iCode *lic) 
2714 {
2715     int i;
2716     iCode *ic;
2717     bitVect *rsave;
2718     sym_link *dtype;
2719
2720     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2721     /* look for call */
2722     for (ic = lic ; ic ; ic = ic->next) 
2723         if (ic->op == CALL || ic->op == PCALL)
2724             break;
2725
2726     if (!ic) {
2727         fprintf(stderr,"found parameter push with no function call\n");
2728         return ;
2729     }
2730
2731     /* if the registers have been saved already then
2732     do nothing */
2733     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2734         return ;
2735
2736     /* find the registers in use at this time 
2737     and push them away to safety */
2738     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2739                           ic->rUsed);
2740
2741     ic->regsSaved = 1;
2742     if (options.useXstack) {
2743         if (bitVectBitValue(rsave,R0_IDX))
2744             pic16_emitcode("mov","b,r0");
2745         pic16_emitcode("mov","r0,%s",spname);
2746         for (i = 0 ; i < pic16_nRegs ; i++) {
2747             if (bitVectBitValue(rsave,i)) {
2748                 if (i == R0_IDX)
2749                     pic16_emitcode("mov","a,b");
2750                 else
2751                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2752                 pic16_emitcode("movx","@r0,a");
2753                 pic16_emitcode("inc","r0");
2754             }
2755         }
2756         pic16_emitcode("mov","%s,r0",spname);
2757         if (bitVectBitValue(rsave,R0_IDX))
2758             pic16_emitcode("mov","r0,b");           
2759     }// else
2760     //for (i = 0 ; i < pic16_nRegs ; i++) {
2761     //    if (bitVectBitValue(rsave,i))
2762     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2763     //}
2764
2765     dtype = operandType(IC_LEFT(ic));
2766     if (currFunc && dtype && 
2767         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2768         IFFUNC_ISISR(currFunc->type) &&
2769         !ic->bankSaved) 
2770
2771         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2772
2773 }
2774 /*-----------------------------------------------------------------*/
2775 /* unsaveRegisters - pop the pushed registers                      */
2776 /*-----------------------------------------------------------------*/
2777 static void unsaveRegisters (iCode *ic)
2778 {
2779     int i;
2780     bitVect *rsave;
2781
2782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2783     /* find the registers in use at this time 
2784     and push them away to safety */
2785     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2786                           ic->rUsed);
2787     
2788     if (options.useXstack) {
2789         pic16_emitcode("mov","r0,%s",spname);   
2790         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2791             if (bitVectBitValue(rsave,i)) {
2792                 pic16_emitcode("dec","r0");
2793                 pic16_emitcode("movx","a,@r0");
2794                 if (i == R0_IDX)
2795                     pic16_emitcode("mov","b,a");
2796                 else
2797                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2798             }       
2799
2800         }
2801         pic16_emitcode("mov","%s,r0",spname);
2802         if (bitVectBitValue(rsave,R0_IDX))
2803             pic16_emitcode("mov","r0,b");
2804     } //else
2805     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2806     //    if (bitVectBitValue(rsave,i))
2807     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2808     //}
2809
2810 }  
2811 #endif
2812
2813 #if 0  // patch 14
2814 /*-----------------------------------------------------------------*/
2815 /* pushSide -                                                      */
2816 /*-----------------------------------------------------------------*/
2817 static void pushSide(operand * oper, int size)
2818 {
2819         int offset = 0;
2820     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2821         while (size--) {
2822                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2823                 if (AOP_TYPE(oper) != AOP_REG &&
2824                     AOP_TYPE(oper) != AOP_DIR &&
2825                     strcmp(l,"a") ) {
2826                         pic16_emitcode("mov","a,%s",l);
2827                         pic16_emitcode("push","acc");
2828                 } else
2829                         pic16_emitcode("push","%s",l);
2830         }
2831 }
2832 #endif // patch 14
2833
2834 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2835 {
2836   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2837     pic16_emitpcode(POC_MOVFW, src);
2838     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2839   } else {
2840     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2841         src, pic16_popGet(AOP(op), offset)));
2842   }
2843 }
2844
2845
2846 /*-----------------------------------------------------------------*/
2847 /* assignResultValue - assign results to oper, rescall==1 is       */
2848 /*                     called from genCall() or genPcall()         */
2849 /*-----------------------------------------------------------------*/
2850 static void assignResultValue(operand * oper, int rescall)
2851 {
2852   int size = AOP_SIZE(oper);
2853   int offset=0;
2854   
2855     FENTRY2;
2856 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2857     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2858
2859     if(rescall) {
2860       /* assign result from a call/pcall function() */
2861                 
2862       /* function results are stored in a special order,
2863        * see top of file with Function return policy, or manual */
2864
2865       if(size <= 4) {
2866         /* 8-bits, result in WREG */
2867         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2868                         
2869         if(size>1) {
2870           /* 16-bits, result in PRODL:WREG */
2871           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2872         }
2873                         
2874         if(size>2) {
2875           /* 24-bits, result in PRODH:PRODL:WREG */
2876           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2877         }
2878                         
2879         if(size>3) {
2880           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2881           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2882         }
2883       
2884       } else {
2885         /* >32-bits, result on stack, and FSR0 points to beginning.
2886          * Fix stack when done */
2887         /* FIXME FIXME */
2888 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2889         while (size--) {
2890 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2891 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2892                 
2893           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2894           GpsuedoStkPtr++;
2895         }
2896                         
2897         /* fix stack */
2898         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2899         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2900         if(STACK_MODEL_LARGE) {
2901           emitSKPNC;
2902           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2903         }
2904       }                 
2905     } else {
2906       int areg = 0;             /* matching argument register */
2907       
2908 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2909       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2910
2911
2912       /* its called from genReceive (probably) -- VR */
2913       /* I hope this code will not be called from somewhere else in the future! 
2914        * We manually set the pseudo stack pointer in genReceive. - dw
2915        */
2916       if(!GpsuedoStkPtr && _G.useWreg) {
2917 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2918
2919         /* The last byte in the assignment is in W */
2920         if(areg <= GpsuedoStkPtr) {
2921           size--;
2922           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2923           offset++;
2924 //          debugf("receive from WREG\n", 0);
2925         }
2926         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2927       }
2928 //      GpsuedoStkPtr++;
2929       _G.stack_lat = AOP_SIZE(oper)-1;
2930
2931       while (size) {
2932         size--;
2933         GpsuedoStkPtr++;
2934         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2935 //        debugf("receive from STACK\n", 0);
2936         offset++;
2937       }
2938     }
2939 }
2940
2941
2942 /*-----------------------------------------------------------------*/
2943 /* genIpush - generate code for pushing this gets a little complex */
2944 /*-----------------------------------------------------------------*/
2945 static void genIpush (iCode *ic)
2946 {
2947 //  int size, offset=0;
2948
2949   FENTRY;
2950   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2951
2952   if(ic->parmPush) {
2953     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2954
2955     /* send to stack as normal */
2956     addSet(&_G.sendSet,ic);
2957 //    addSetHead(&_G.sendSet,ic);
2958     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2959   }
2960
2961         
2962 #if 0
2963     int size, offset = 0 ;
2964     char *l;
2965
2966
2967     /* if this is not a parm push : ie. it is spill push 
2968     and spill push is always done on the local stack */
2969     if (!ic->parmPush) {
2970
2971         /* and the item is spilt then do nothing */
2972         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2973             return ;
2974
2975         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2976         size = AOP_SIZE(IC_LEFT(ic));
2977         /* push it on the stack */
2978         while(size--) {
2979             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2980             if (*l == '#') {
2981                 MOVA(l);
2982                 l = "acc";
2983             }
2984             pic16_emitcode("push","%s",l);
2985         }
2986         return ;        
2987     }
2988
2989     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2990 #endif
2991 }
2992
2993 /*-----------------------------------------------------------------*/
2994 /* genIpop - recover the registers: can happen only for spilling   */
2995 /*-----------------------------------------------------------------*/
2996 static void genIpop (iCode *ic)
2997 {
2998   FENTRY;
2999   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3000 #if 0
3001     int size,offset ;
3002
3003
3004     /* if the temp was not pushed then */
3005     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3006         return ;
3007
3008     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3009     size = AOP_SIZE(IC_LEFT(ic));
3010     offset = (size-1);
3011     while (size--) 
3012         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3013                                    FALSE,TRUE));
3014
3015     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3016 #endif
3017 }
3018
3019 #if 0
3020 /*-----------------------------------------------------------------*/
3021 /* unsaverbank - restores the resgister bank from stack            */
3022 /*-----------------------------------------------------------------*/
3023 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3024 {
3025   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3026 #if 0
3027     int i;
3028     asmop *aop ;
3029     regs *r = NULL;
3030
3031     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3032     if (popPsw) {
3033         if (options.useXstack) {
3034             aop = newAsmop(0);
3035             r = getFreePtr(ic,&aop,FALSE);
3036             
3037             
3038             pic16_emitcode("mov","%s,_spx",r->name);
3039             pic16_emitcode("movx","a,@%s",r->name);
3040             pic16_emitcode("mov","psw,a");
3041             pic16_emitcode("dec","%s",r->name);
3042             
3043         }else
3044             pic16_emitcode ("pop","psw");
3045     }
3046
3047     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3048         if (options.useXstack) {       
3049             pic16_emitcode("movx","a,@%s",r->name);
3050             //pic16_emitcode("mov","(%s+%d),a",
3051             //       regspic16[i].base,8*bank+regspic16[i].offset);
3052             pic16_emitcode("dec","%s",r->name);
3053
3054         } else 
3055           pic16_emitcode("pop",""); //"(%s+%d)",
3056         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3057     }
3058
3059     if (options.useXstack) {
3060
3061         pic16_emitcode("mov","_spx,%s",r->name);
3062         pic16_freeAsmop(NULL,aop,ic,TRUE);
3063
3064     }
3065 #endif 
3066 }
3067
3068 /*-----------------------------------------------------------------*/
3069 /* saverbank - saves an entire register bank on the stack          */
3070 /*-----------------------------------------------------------------*/
3071 static void saverbank (int bank, iCode *ic, bool pushPsw)
3072 {
3073   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3074 #if 0
3075     int i;
3076     asmop *aop ;
3077     regs *r = NULL;
3078
3079     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3080     if (options.useXstack) {
3081
3082         aop = newAsmop(0);
3083         r = getFreePtr(ic,&aop,FALSE);  
3084         pic16_emitcode("mov","%s,_spx",r->name);
3085
3086     }
3087
3088     for (i = 0 ; i < pic16_nRegs ;i++) {
3089         if (options.useXstack) {
3090             pic16_emitcode("inc","%s",r->name);
3091             //pic16_emitcode("mov","a,(%s+%d)",
3092             //         regspic16[i].base,8*bank+regspic16[i].offset);
3093             pic16_emitcode("movx","@%s,a",r->name);           
3094         } else 
3095           pic16_emitcode("push","");// "(%s+%d)",
3096                      //regspic16[i].base,8*bank+regspic16[i].offset);
3097     }
3098     
3099     if (pushPsw) {
3100         if (options.useXstack) {
3101             pic16_emitcode("mov","a,psw");
3102             pic16_emitcode("movx","@%s,a",r->name);     
3103             pic16_emitcode("inc","%s",r->name);
3104             pic16_emitcode("mov","_spx,%s",r->name);       
3105             pic16_freeAsmop (NULL,aop,ic,TRUE);
3106             
3107         } else
3108             pic16_emitcode("push","psw");
3109         
3110         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3111     }
3112     ic->bankSaved = 1;
3113 #endif
3114 }
3115 #endif  /* 0 */
3116
3117
3118 static int wparamCmp(void *p1, void *p2)
3119 {
3120   return (!strcmp((char *)p1, (char *)p2));
3121 }
3122
3123 int inWparamList(char *s)
3124 {
3125   return isinSetWith(wparamList, s, wparamCmp);
3126
3127
3128
3129 /*-----------------------------------------------------------------*/
3130 /* genCall - generates a call statement                            */
3131 /*-----------------------------------------------------------------*/
3132 static void genCall (iCode *ic)
3133 {
3134   sym_link *ftype;   
3135   int stackParms=0;
3136   int use_wreg=0;
3137   int inwparam=0;
3138   char *fname;
3139   
3140     FENTRY;
3141
3142     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3143     /* if caller saves & we have not saved then */
3144 //    if (!ic->regsSaved)
3145 //      saveRegisters(ic);
3146
3147         /* initialise stackParms for IPUSH pushes */
3148 //      stackParms = psuedoStkPtr;
3149 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3150     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3151     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3152
3153 #if 0
3154     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3155 #endif
3156
3157     /* if send set is not empty the assign */
3158     if (_G.sendSet) {
3159       iCode *sic;
3160       int psuedoStkPtr=-1; 
3161       int firstTimeThruLoop = 1;
3162
3163
3164         /* reverse sendSet if function is not reentrant */
3165         if(!IFFUNC_ISREENT(ftype))
3166           _G.sendSet = reverseSet(_G.sendSet);
3167
3168         /* First figure how many parameters are getting passed */
3169         stackParms = 0;
3170         use_wreg = 0;
3171         
3172         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3173           int size;
3174 //          int offset = 0;
3175
3176             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3177             size = AOP_SIZE(IC_LEFT(sic));
3178
3179             stackParms += size;
3180
3181             /* pass the last byte through WREG */
3182             if(inwparam) {
3183
3184               while (size--) {
3185                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3186                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3187                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3188
3189                 if(!firstTimeThruLoop) {
3190                   /* If this is not the first time we've been through the loop
3191                    * then we need to save the parameter in a temporary
3192                    * register. The last byte of the last parameter is
3193                    * passed in W. */
3194
3195                   pushw();
3196 //                  --psuedoStkPtr;             // sanity check
3197                   use_wreg = 1;
3198                 }
3199                 
3200                 firstTimeThruLoop=0;
3201
3202                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3203
3204 //                offset++;
3205               }
3206             } else {
3207               /* all arguments are passed via stack */
3208               use_wreg = 0;
3209
3210               while (size--) {
3211                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3212                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3213                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3214
3215 //                pushaop(AOP(IC_LEFT(sic)), size);
3216                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3217                 pushw();
3218               }
3219             }
3220
3221             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3222           }
3223
3224           if(inwparam) {
3225             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3226               pushw();  /* save last parameter to stack if functions has varargs */
3227               use_wreg = 0;
3228             } else
3229               use_wreg = 1;
3230           } else use_wreg = 0;
3231
3232           _G.stackRegSet = _G.sendSet;
3233           _G.sendSet = NULL;
3234     }
3235
3236     /* make the call */
3237     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3238
3239     GpsuedoStkPtr=0;
3240     
3241     /* if we need to assign a result value */
3242     if ((IS_ITEMP(IC_RESULT(ic))
3243           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3244               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3245         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3246
3247       _G.accInUse++;
3248       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3249       _G.accInUse--;
3250
3251       assignResultValue(IC_RESULT(ic), 1);
3252
3253       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3254                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3255                 
3256       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3257     }
3258
3259     if(!stackParms && ic->parmBytes) {
3260       stackParms = ic->parmBytes;
3261     }
3262       
3263     stackParms -= use_wreg;
3264     
3265     if(stackParms>0) {
3266       if(stackParms == 1) {
3267         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3268       } else {
3269         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3270         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3271       }
3272       if(STACK_MODEL_LARGE) {
3273         emitSKPNC;
3274         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3275       }
3276     }
3277
3278 #if 0
3279     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3280 #endif
3281
3282     /* adjust the stack for parameters if required */
3283 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3284
3285 #if 0
3286       /* if register bank was saved then pop them */
3287       if (ic->bankSaved)
3288         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3289
3290       /* if we hade saved some registers then unsave them */
3291       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3292         unsaveRegisters (ic);
3293 #endif
3294 }
3295
3296
3297
3298 /*-----------------------------------------------------------------*/
3299 /* genPcall - generates a call by pointer statement                */
3300 /*            new version, created from genCall - HJD              */
3301 /*-----------------------------------------------------------------*/
3302 static void genPcall (iCode *ic)
3303 {
3304   sym_link *ftype, *fntype;
3305   int stackParms=0;
3306   symbol *retlbl = newiTempLabel(NULL);
3307   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3308   
3309     FENTRY;
3310
3311     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3312     fntype = operandType( IC_LEFT(ic) )->next;
3313
3314     /* if send set is not empty the assign */
3315     if (_G.sendSet) {
3316       iCode *sic;
3317       int psuedoStkPtr=-1; 
3318
3319       /* reverse sendSet if function is not reentrant */
3320       if(!IFFUNC_ISREENT(fntype))
3321         _G.sendSet = reverseSet(_G.sendSet);
3322
3323       stackParms = 0;
3324       
3325       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3326         int size;
3327
3328           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329           size = AOP_SIZE(IC_LEFT(sic));
3330           stackParms += size;
3331
3332           /* all parameters are passed via stack, since WREG is clobbered
3333            * by the calling sequence */
3334           while (size--) {
3335             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3336             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3337             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3338
3339             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3340             pushw();
3341           }
3342
3343           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3344       }
3345
3346       _G.stackRegSet = _G.sendSet;
3347       _G.sendSet = NULL;
3348     }
3349
3350     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3351
3352     // push return address
3353     // push $ on return stack, then replace with retlbl
3354
3355     pic16_emitpcodeNULLop(POC_PUSH);
3356
3357     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3358     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3359     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3360     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3361     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3362     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3363
3364     /* make the call by writing the pointer into pc */
3365     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3366     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3367
3368     // note: MOVFF to PCL not allowed
3369     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3370     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3371
3372
3373     /* return address is here: (X) */
3374     pic16_emitpLabelFORCE(retlbl->key);
3375
3376     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3377
3378     GpsuedoStkPtr=0;
3379     /* if we need assign a result value */
3380     if ((IS_ITEMP(IC_RESULT(ic))
3381           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3382               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3383         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3384
3385       _G.accInUse++;
3386       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3387       _G.accInUse--;
3388
3389       assignResultValue(IC_RESULT(ic), 1);
3390
3391       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3392               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3393                 
3394       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3395     }
3396
3397 //    stackParms -= use_wreg;
3398     
3399     if(stackParms>0) {
3400       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3401       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3402       if(STACK_MODEL_LARGE) {
3403         /* this implies that stackParms < 256 !!! -- VR */
3404         emitSKPNC;
3405         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3406       }
3407     }
3408 }
3409
3410 /*-----------------------------------------------------------------*/
3411 /* resultRemat - result  is rematerializable                       */
3412 /*-----------------------------------------------------------------*/
3413 static int resultRemat (iCode *ic)
3414 {
3415   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3416   if (SKIP_IC(ic) || ic->op == IFX)
3417     return 0;
3418
3419   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3420     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3421     if (sym->remat && !POINTER_SET(ic)) 
3422       return 1;
3423   }
3424
3425   return 0;
3426 }
3427
3428 #if defined(__BORLANDC__) || defined(_MSC_VER)
3429 #define STRCASECMP stricmp
3430 #else
3431 #define STRCASECMP strcasecmp
3432 #endif
3433
3434 #if 0
3435 /*-----------------------------------------------------------------*/
3436 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3437 /*-----------------------------------------------------------------*/
3438 static bool inExcludeList(char *s)
3439 {
3440   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3441     int i =0;
3442     
3443     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3444     if (options.excludeRegs[i] &&
3445     STRCASECMP(options.excludeRegs[i],"none") == 0)
3446         return FALSE ;
3447
3448     for ( i = 0 ; options.excludeRegs[i]; i++) {
3449         if (options.excludeRegs[i] &&
3450         STRCASECMP(s,options.excludeRegs[i]) == 0)
3451             return TRUE;
3452     }
3453     return FALSE ;
3454 }
3455 #endif
3456
3457 /*-----------------------------------------------------------------*/
3458 /* genFunction - generated code for function entry                 */
3459 /*-----------------------------------------------------------------*/
3460 static void genFunction (iCode *ic)
3461 {
3462   symbol *sym;
3463   sym_link *ftype;
3464   
3465     FENTRY;
3466     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3467
3468     pic16_labelOffset += (max_key+4);
3469     max_key=0;
3470     GpsuedoStkPtr=0;
3471     _G.nRegsSaved = 0;
3472         
3473     ftype = operandType(IC_LEFT(ic));
3474     sym = OP_SYMBOL(IC_LEFT(ic));
3475
3476     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3477       /* create an absolute section at the interrupt vector:
3478        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3479       symbol *asym;
3480       char asymname[128];
3481       pBlock *apb;
3482
3483         {
3484           int i, found=-1;
3485
3486             sym = OP_SYMBOL( IC_LEFT(ic));
3487             for(i=0;i<=2;i++) {
3488               if(interrupts[i]->name
3489                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3490                   found = i;
3491                   break;
3492               }
3493             }
3494                         
3495             if(found == -1) {
3496               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3497                             __FILE__, __LINE__, sym->name);
3498               assert( 0 );
3499             }
3500             _G.interruptvector = found;
3501         }
3502
3503         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3504         asym = newSymbol(asymname, 0);
3505
3506         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3507         pic16_addpBlock( apb );
3508
3509         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3510         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3511         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3512                 
3513         /* mark the end of this tiny function */
3514         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3515
3516         {
3517           absSym *abSym;
3518
3519             abSym = Safe_calloc(1, sizeof(absSym));
3520             strcpy(abSym->name, asymname);
3521
3522             switch( _G.interruptvector ) {
3523               case 0: abSym->address = 0x000000; break;
3524               case 1: abSym->address = 0x000008; break;
3525               case 2: abSym->address = 0x000018; break;
3526             }
3527
3528             /* relocate interrupt vectors if needed */
3529             abSym->address += pic16_options.ivt_loc;
3530
3531             addSet(&absSymSet, abSym);
3532         }
3533     }
3534
3535     /* create the function header */
3536     pic16_emitcode(";","-----------------------------------------");
3537     pic16_emitcode(";"," function %s",sym->name);
3538     pic16_emitcode(";","-----------------------------------------");
3539
3540     pic16_emitcode("","%s:",sym->rname);
3541     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3542
3543
3544     {
3545       absSym *ab;
3546
3547         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3548           if(!strcmp(ab->name, sym->rname)) {
3549             pic16_pBlockConvert2Absolute(pb);
3550             break;
3551           }
3552         }
3553     }
3554
3555
3556     if(IFFUNC_ISNAKED(ftype)) {
3557       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3558       return;
3559     }
3560         
3561     /* if critical function then turn interrupts off */
3562     if (IFFUNC_ISCRITICAL(ftype)) {
3563       //pic16_emitcode("clr","ea");
3564     }
3565
3566     _G.fregsUsed = sym->regsUsed;
3567
3568     /* if this is an interrupt service routine then
3569      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3570     if (IFFUNC_ISISR(sym->type)) {
3571         _G.usefastretfie = 1;   /* use shadow registers by default */
3572         
3573         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3574         if(!(_G.interruptvector == 1)) {
3575           /* do not save WREG,STATUS,BSR for high priority interrupts
3576            * because they are stored in the hardware shadow registers already */
3577           _G.usefastretfie = 0;
3578           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3579           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3580           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3581         }
3582
3583         /* these should really be optimized somehow, because not all
3584          * interrupt handlers modify them */
3585         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3586         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3587         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3588         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3589         
3590 //        pic16_pBlockConvert2ISR(pb);
3591                 
3592     }
3593
3594     /* emit code to setup stack frame if user enabled,
3595      * and function is not main() */
3596          
3597     //fprintf(stderr, "function name: %s\n", sym->name);
3598     if(strcmp(sym->name, "main")) {
3599       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3600         /* setup the stack frame */
3601         if(STACK_MODEL_LARGE)
3602           pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3603         pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3604 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3605         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3606         if(STACK_MODEL_LARGE)
3607           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3608       }
3609     }
3610
3611     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3612           && sym->stack) {
3613
3614       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3615
3616       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3617       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3618       emitSKPC;
3619       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3620     }
3621           
3622     if(inWparamList(sym->name)) {
3623       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3624         _G.useWreg = 0;
3625       else
3626         _G.useWreg = 1;
3627     } else
3628       _G.useWreg = 0;
3629
3630     /* if callee-save to be used for this function
3631      * then save the registers being used in this function */
3632 //    if (IFFUNC_CALLEESAVES(sym->type))
3633     {
3634       int i;
3635
3636         /* if any registers used */
3637         if (sym->regsUsed) {
3638           /* save the registers used */
3639           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3640           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3641           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3642             if (bitVectBitValue(sym->regsUsed,i)) {
3643               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3644               _G.nRegsSaved++;
3645
3646               if(!pic16_regWithIdx(i)->wasUsed) {
3647                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3648                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3649                 pic16_regWithIdx(i)->wasUsed = 1;
3650               }
3651             }
3652           }
3653           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3654         }
3655     }
3656         
3657     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3658 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3659 }
3660
3661 /*-----------------------------------------------------------------*/
3662 /* genEndFunction - generates epilogue for functions               */
3663 /*-----------------------------------------------------------------*/
3664 static void genEndFunction (iCode *ic)
3665 {
3666   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3667
3668     FENTRY;
3669
3670     if(IFFUNC_ISNAKED(sym->type)) {
3671       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3672       return;
3673     }
3674
3675     _G.stack_lat = 0;
3676
3677     /* add code for ISCRITICAL */
3678     if(IFFUNC_ISCRITICAL(sym->type)) {
3679       /* if critical function, turn on interrupts */
3680       
3681       /* TODO: add code here -- VR */
3682     }
3683     
3684     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3685           && sym->stack) {
3686       if (sym->stack == 1) {
3687         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
3688         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3689       } else {
3690         // we have to add more than one...
3691         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
3692         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3693         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3694         emitSKPNC;
3695         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3696         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3697         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
3698       }
3699     }
3700
3701 //    sym->regsUsed = _G.fregsUsed;
3702     
3703     /* now we need to restore the registers */
3704     /* if any registers used */
3705     if (sym->regsUsed) {
3706       int i;
3707
3708         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3709         /* restore registers used */
3710         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3711         for ( i = sym->regsUsed->size; i >= 0; i--) {
3712           if (bitVectBitValue(sym->regsUsed,i)) {
3713             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3714             _G.nRegsSaved--;
3715           }
3716         }
3717         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3718
3719     }
3720
3721     if(strcmp(sym->name, "main")) {
3722       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3723         /* restore stack frame */
3724         if(STACK_MODEL_LARGE)
3725           pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3726 //          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3727         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3728 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3729       }
3730     }
3731
3732     _G.useWreg = 0;
3733
3734     if (IFFUNC_ISISR(sym->type)) {
3735       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3736       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3737       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3738       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3739
3740       if(!(_G.interruptvector == 1)) {
3741         /* do not restore interrupt vector for WREG,STATUS,BSR
3742          * for high priority interrupt, see genFunction */
3743         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3744         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3745         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3746       }
3747       _G.interruptvector = 0;           /* sanity check */
3748
3749
3750       /* if debug then send end of function */
3751 /*      if (options.debug && currFunc)  */
3752       if (currFunc) {
3753         debugFile->writeEndFunction (currFunc, ic, 1);
3754       }
3755         
3756       if(_G.usefastretfie)
3757         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3758       else
3759         pic16_emitpcodeNULLop(POC_RETFIE);
3760
3761       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3762       
3763       _G.usefastretfie = 0;
3764       return;
3765     }
3766
3767     if (IFFUNC_ISCRITICAL(sym->type)) {
3768       pic16_emitcode("setb","ea");
3769     }
3770
3771     /* if debug then send end of function */
3772     if (currFunc) {
3773       debugFile->writeEndFunction (currFunc, ic, 1);
3774     }
3775
3776     /* insert code to restore stack frame, if user enabled it
3777      * and function is not main() */
3778          
3779
3780     pic16_emitpcodeNULLop(POC_RETURN);
3781
3782     /* Mark the end of a function */
3783     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3784 }
3785
3786
3787 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3788 {
3789   if(is_LitOp(op)) {
3790     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3791       if(lit == 0) {
3792         pic16_emitpcode(POC_CLRF, dest);
3793       } else {
3794         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3795         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3796       }
3797   } else {
3798     if(dest->type == PO_WREG && (offset == 0)) {
3799       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3800       return;
3801     }
3802     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3803   }
3804 }
3805
3806 /*-----------------------------------------------------------------*/
3807 /* genRet - generate code for return statement                     */
3808 /*-----------------------------------------------------------------*/
3809 static void genRet (iCode *ic)
3810 {
3811   int size;
3812   operand *left;
3813
3814     FENTRY;
3815         /* if we have no return value then
3816          * just generate the "ret" */
3817         
3818         if (!IC_LEFT(ic)) 
3819                 goto jumpret;       
3820     
3821         /* we have something to return then
3822          * move the return value into place */
3823         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3824         size = AOP_SIZE(IC_LEFT(ic));
3825
3826         if(size <= 4) {
3827                 if(size>3) {
3828                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3829 //                      pic16_emitpcode(POC_MOVFF,
3830 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3831                 }
3832                 if(size>2) {
3833                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3834 //                      pic16_emitpcode(POC_MOVFF,
3835 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3836                 }
3837                 if(size>1) {
3838                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3839 //                      pic16_emitpcode(POC_MOVFF,
3840 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3841                 }
3842
3843 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3844
3845                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3846 //              pic16_emitpcode(POC_MOVFF,
3847 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3848
3849         } else {
3850                 /* >32-bits, setup stack and FSR0 */
3851                 while (size--) {
3852 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3853 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3854
3855                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3856
3857 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3858                         GpsuedoStkPtr++;
3859                 }
3860                         
3861                 /* setup FSR0 */
3862                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3863                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3864
3865                 if(STACK_MODEL_LARGE) {
3866                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3867                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3868                 } else {
3869                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3870                 }
3871         }
3872                                 
3873 #if 0
3874         /* old code, left here for reference -- VR */    
3875         while (size--) {
3876           char *l ;
3877
3878                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3879                         /* #NOCHANGE */
3880                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3881                         pic16_emitpcomment("push %s",l);
3882                         pushed++;
3883                 } else {
3884                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3885                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3886                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3887                         
3888                         if (strcmp(fReturn[offset],l)) {
3889                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3890                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3891                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3892                                 } else {
3893                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3894                                 }
3895                                 
3896                                 if(size) {
3897                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3898                                 }
3899                                 offset++;
3900                         }
3901                 }
3902         }    
3903
3904         if (pushed) {
3905                 while(pushed) {
3906                         pushed--;
3907                         if (strcmp(fReturn[pushed],"a"))
3908                                 pic16_emitcode("pop",fReturn[pushed]);
3909                         else
3910                                 pic16_emitcode("pop","acc");
3911                 }
3912         }
3913 #endif
3914
3915
3916         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3917     
3918 jumpret:
3919         /* generate a jump to the return label
3920          * if the next is not the return statement */
3921         if (!(ic->next && ic->next->op == LABEL
3922                 && IC_LABEL(ic->next) == returnLabel)) {
3923         
3924                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3925                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3926         }
3927 }
3928
3929 /*-----------------------------------------------------------------*/
3930 /* genLabel - generates a label                                    */
3931 /*-----------------------------------------------------------------*/
3932 static void genLabel (iCode *ic)
3933 {
3934   FENTRY;
3935
3936   /* special case never generate */
3937   if (IC_LABEL(ic) == entryLabel)
3938     return ;
3939
3940   pic16_emitpLabel(IC_LABEL(ic)->key);
3941 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3942 }
3943
3944 /*-----------------------------------------------------------------*/
3945 /* genGoto - generates a goto                                      */
3946 /*-----------------------------------------------------------------*/
3947 //tsd
3948 static void genGoto (iCode *ic)
3949 {
3950   FENTRY;
3951   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3952 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3953 }
3954
3955
3956 /*-----------------------------------------------------------------*/
3957 /* genMultbits :- multiplication of bits                           */
3958 /*-----------------------------------------------------------------*/
3959 static void genMultbits (operand *left, 
3960                          operand *right, 
3961                          operand *result)
3962 {
3963   FENTRY;
3964
3965   if(!pic16_sameRegs(AOP(result),AOP(right)))
3966     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3967
3968   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3969   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3970   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3971
3972 }
3973
3974
3975 /*-----------------------------------------------------------------*/
3976 /* genMultOneByte : 8 bit multiplication & division                */
3977 /*-----------------------------------------------------------------*/
3978 static void genMultOneByte (operand *left,
3979                             operand *right,
3980                             operand *result)
3981 {
3982
3983   FENTRY;
3984   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3985   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3986
3987   /* (if two literals, the value is computed before) */
3988   /* if one literal, literal on the right */
3989   if (AOP_TYPE(left) == AOP_LIT){
3990     operand *t = right;
3991     right = left;
3992     left = t;
3993   }
3994
3995         /* size is already checked in genMult == 1 */
3996 //      size = AOP_SIZE(result);
3997
3998         if (AOP_TYPE(right) == AOP_LIT){
3999                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4000                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4001                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4002                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4003         } else {
4004                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4005                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4006                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4007                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4008         }
4009         
4010         pic16_genMult8X8_8 (left, right,result);
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genMultOneWord : 16 bit multiplication                          */
4015 /*-----------------------------------------------------------------*/
4016 static void genMultOneWord (operand *left,
4017                             operand *right,
4018                             operand *result)
4019 {
4020   FENTRY;
4021   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4022   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4023
4024   /* (if two literals, the value is computed before)
4025    * if one literal, literal on the right */
4026   if (AOP_TYPE(left) == AOP_LIT){
4027     operand *t = right;
4028     right = left;
4029     left = t;
4030   }
4031
4032   /* size is checked already == 2 */
4033 //  size = AOP_SIZE(result);
4034
4035   if (AOP_TYPE(right) == AOP_LIT) {
4036     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4037       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4038       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4039       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4040   } else {
4041     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4042       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4043       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4044       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4045   }
4046         
4047   pic16_genMult16X16_16(left, right,result);
4048 }
4049
4050 /*-----------------------------------------------------------------*/
4051 /* genMultOneLong : 32 bit multiplication                          */
4052 /*-----------------------------------------------------------------*/
4053 static void genMultOneLong (operand *left,
4054                             operand *right,
4055                             operand *result)
4056 {
4057   FENTRY;
4058   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4059   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4060
4061   /* (if two literals, the value is computed before)
4062    * if one literal, literal on the right */
4063   if (AOP_TYPE(left) == AOP_LIT){
4064     operand *t = right;
4065     right = left;
4066     left = t;
4067   }
4068
4069   /* size is checked already == 4 */
4070 //  size = AOP_SIZE(result);
4071
4072   if (AOP_TYPE(right) == AOP_LIT) {
4073     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4074         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4075         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4076         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4077   } else {
4078     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4079         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4080         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4081         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4082   }
4083         
4084   pic16_genMult32X32_32(left, right,result);
4085 }
4086
4087
4088
4089 /*-----------------------------------------------------------------*/
4090 /* genMult - generates code for multiplication                     */
4091 /*-----------------------------------------------------------------*/
4092 static void genMult (iCode *ic)
4093 {
4094   operand *left = IC_LEFT(ic);
4095   operand *right = IC_RIGHT(ic);
4096   operand *result= IC_RESULT(ic);   
4097
4098     FENTRY;
4099         /* assign the amsops */
4100         pic16_aopOp (left,ic,FALSE);
4101         pic16_aopOp (right,ic,FALSE);
4102         pic16_aopOp (result,ic,TRUE);
4103
4104         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4105
4106         /* special cases first *
4107         * both are bits */
4108         if (AOP_TYPE(left) == AOP_CRY
4109                 && AOP_TYPE(right)== AOP_CRY) {
4110                 genMultbits(left,right,result);
4111           goto release ;
4112         }
4113
4114         /* if both are of size == 1 */
4115         if(AOP_SIZE(left) == 1
4116                 && AOP_SIZE(right) == 1) {
4117                 genMultOneByte(left,right,result);
4118           goto release ;
4119         }
4120
4121         /* if both are of size == 2 */
4122         if(AOP_SIZE(left) == 2
4123                 && AOP_SIZE(right) == 2) {
4124                 genMultOneWord(left, right, result);
4125           goto release;
4126         }
4127         
4128         /* if both are of size == 4 */
4129         if(AOP_SIZE(left) == 4
4130                 && AOP_SIZE(right) == 4) {
4131                 genMultOneLong(left, right, result);
4132           goto release;
4133         }
4134         
4135         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4136
4137
4138         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4139         /* should have been converted to function call */
4140         assert(0) ;
4141
4142 release :
4143         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4144         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4145         pic16_freeAsmop(result,NULL,ic,TRUE); 
4146 }
4147
4148 /*-----------------------------------------------------------------*/
4149 /* genDivbits :- division of bits                                  */
4150 /*-----------------------------------------------------------------*/
4151 static void genDivbits (operand *left, 
4152                         operand *right, 
4153                         operand *result)
4154 {
4155   char *l;
4156
4157     FENTRY;
4158     /* the result must be bit */    
4159     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4160     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4161
4162     MOVA(l);    
4163
4164     pic16_emitcode("div","ab");
4165     pic16_emitcode("rrc","a");
4166     pic16_aopPut(AOP(result),"c",0);
4167 }
4168
4169 /*-----------------------------------------------------------------*/
4170 /* genDivOneByte : 8 bit division                                  */
4171 /*-----------------------------------------------------------------*/
4172 static void genDivOneByte (operand *left,
4173                            operand *right,
4174                            operand *result)
4175 {
4176   sym_link *opetype = operandType(result);
4177   char *l ;
4178   symbol *lbl ;
4179   int size,offset;
4180
4181         /* result = divident / divisor
4182          * - divident may be a register or a literal,
4183          * - divisor may be a register or a literal,
4184          * so there are 3 cases (literal / literal is optimized
4185          * by the front-end) to handle.
4186          * In addition we must handle signed and unsigned, which
4187          * result in 6 final different cases -- VR */
4188
4189     FENTRY;
4190     
4191     size = AOP_SIZE(result) - 1;
4192     offset = 1;
4193     /* signed or unsigned */
4194     if (SPEC_USIGN(opetype)) {
4195       pCodeOp *pct1,    /* count */
4196                 *pct2,  /* reste */
4197                 *pct3;  /* temp */
4198       symbol *label1, *label2, *label3;;
4199
4200
4201         /* unsigned is easy */
4202
4203         pct1 = pic16_popGetTempReg(1);
4204         pct2 = pic16_popGetTempReg(1);
4205         pct3 = pic16_popGetTempReg(1);
4206         
4207         label1 = newiTempLabel(NULL);
4208         label2 = newiTempLabel(NULL);
4209         label3 = newiTempLabel(NULL);
4210
4211         /* the following algorithm is extracted from divuint.c */
4212
4213         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4214         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4215         
4216         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4217
4218         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4219         
4220         pic16_emitpLabel(label1->key);
4221         
4222         emitCLRC;
4223         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4224
4225
4226         emitCLRC;
4227         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4228         
4229
4230         emitSKPNC;
4231         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4232         
4233         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4234         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4235         
4236         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4237         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4238         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4239         
4240         pic16_emitpLabel( label3->key );
4241         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4242         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4243         
4244         
4245
4246         pic16_emitpLabel(label2->key);
4247         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4248         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4249         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4250         
4251         /* result is in wreg */
4252         if(AOP_TYPE(result) != AOP_ACC)
4253                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4254
4255         pic16_popReleaseTempReg( pct3, 1);
4256         pic16_popReleaseTempReg( pct2, 1);
4257         pic16_popReleaseTempReg( pct1, 1);
4258
4259         return ;
4260     }
4261
4262     /* signed is a little bit more difficult */
4263
4264     /* save the signs of the operands */
4265     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4266     MOVA(l);    
4267     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4268     pic16_emitcode("push","acc"); /* save it on the stack */
4269
4270     /* now sign adjust for both left & right */
4271     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4272     MOVA(l);       
4273     lbl = newiTempLabel(NULL);
4274     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4275     pic16_emitcode("cpl","a");   
4276     pic16_emitcode("inc","a");
4277     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4278     pic16_emitcode("mov","b,a");
4279
4280     /* sign adjust left side */
4281     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4282     MOVA(l);
4283
4284     lbl = newiTempLabel(NULL);
4285     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4286     pic16_emitcode("cpl","a");
4287     pic16_emitcode("inc","a");
4288     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4289
4290     /* now the division */
4291     pic16_emitcode("div","ab");
4292     /* we are interested in the lower order
4293     only */
4294     pic16_emitcode("mov","b,a");
4295     lbl = newiTempLabel(NULL);
4296     pic16_emitcode("pop","acc");   
4297     /* if there was an over flow we don't 
4298     adjust the sign of the result */
4299     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4300     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4301     CLRC;
4302     pic16_emitcode("clr","a");
4303     pic16_emitcode("subb","a,b");
4304     pic16_emitcode("mov","b,a");
4305     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4306
4307     /* now we are done */
4308     pic16_aopPut(AOP(result),"b",0);
4309     if(size > 0){
4310         pic16_emitcode("mov","c,b.7");
4311         pic16_emitcode("subb","a,acc");   
4312     }
4313     while (size--)
4314         pic16_aopPut(AOP(result),"a",offset++);
4315
4316 }
4317
4318 /*-----------------------------------------------------------------*/
4319 /* genDiv - generates code for division                            */
4320 /*-----------------------------------------------------------------*/
4321 static void genDiv (iCode *ic)
4322 {
4323     operand *left = IC_LEFT(ic);
4324     operand *right = IC_RIGHT(ic);
4325     operand *result= IC_RESULT(ic);   
4326
4327
4328         /* Division is a very lengthy algorithm, so it is better
4329          * to call support routines than inlining algorithm.
4330          * Division functions written here just in case someone
4331          * wants to inline and not use the support libraries -- VR */
4332
4333     FENTRY;
4334     
4335     /* assign the amsops */
4336     pic16_aopOp (left,ic,FALSE);
4337     pic16_aopOp (right,ic,FALSE);
4338     pic16_aopOp (result,ic,TRUE);
4339
4340     /* special cases first */
4341     /* both are bits */
4342     if (AOP_TYPE(left) == AOP_CRY &&
4343         AOP_TYPE(right)== AOP_CRY) {
4344         genDivbits(left,right,result);
4345         goto release ;
4346     }
4347
4348     /* if both are of size == 1 */
4349     if (AOP_SIZE(left) == 1 &&
4350         AOP_SIZE(right) == 1 ) {
4351         genDivOneByte(left,right,result);
4352         goto release ;
4353     }
4354
4355     /* should have been converted to function call */
4356     assert(0);
4357 release :
4358     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4359     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360     pic16_freeAsmop(result,NULL,ic,TRUE); 
4361 }
4362
4363 /*-----------------------------------------------------------------*/
4364 /* genModbits :- modulus of bits                                   */
4365 /*-----------------------------------------------------------------*/
4366 static void genModbits (operand *left, 
4367                         operand *right, 
4368                         operand *result)
4369 {
4370   char *l;
4371
4372     FENTRY;  
4373     
4374     werror(W_POSSBUG2, __FILE__, __LINE__);
4375     /* the result must be bit */    
4376     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4377     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4378
4379     MOVA(l);       
4380
4381     pic16_emitcode("div","ab");
4382     pic16_emitcode("mov","a,b");
4383     pic16_emitcode("rrc","a");
4384     pic16_aopPut(AOP(result),"c",0);
4385 }
4386
4387 /*-----------------------------------------------------------------*/
4388 /* genModOneByte : 8 bit modulus                                   */
4389 /*-----------------------------------------------------------------*/
4390 static void genModOneByte (operand *left,
4391                            operand *right,
4392                            operand *result)
4393 {
4394   sym_link *opetype = operandType(result);
4395   char *l ;
4396   symbol *lbl ;
4397
4398     FENTRY;
4399     werror(W_POSSBUG2, __FILE__, __LINE__);
4400
4401     /* signed or unsigned */
4402     if (SPEC_USIGN(opetype)) {
4403         /* unsigned is easy */
4404         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4405         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4406         MOVA(l);    
4407         pic16_emitcode("div","ab");
4408         pic16_aopPut(AOP(result),"b",0);
4409         return ;
4410     }
4411
4412     /* signed is a little bit more difficult */
4413
4414     /* save the signs of the operands */
4415     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4416     MOVA(l);
4417
4418     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4419     pic16_emitcode("push","acc"); /* save it on the stack */
4420
4421     /* now sign adjust for both left & right */
4422     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4423     MOVA(l);
4424
4425     lbl = newiTempLabel(NULL);
4426     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4427     pic16_emitcode("cpl","a");   
4428     pic16_emitcode("inc","a");
4429     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4430     pic16_emitcode("mov","b,a"); 
4431
4432     /* sign adjust left side */
4433     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4434     MOVA(l);
4435
4436     lbl = newiTempLabel(NULL);
4437     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4438     pic16_emitcode("cpl","a");   
4439     pic16_emitcode("inc","a");
4440     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4441
4442     /* now the multiplication */
4443     pic16_emitcode("div","ab");
4444     /* we are interested in the lower order
4445     only */
4446     lbl = newiTempLabel(NULL);
4447     pic16_emitcode("pop","acc");   
4448     /* if there was an over flow we don't 
4449     adjust the sign of the result */
4450     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4451     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4452     CLRC ;
4453     pic16_emitcode("clr","a");
4454     pic16_emitcode("subb","a,b");
4455     pic16_emitcode("mov","b,a");
4456     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4457
4458     /* now we are done */
4459     pic16_aopPut(AOP(result),"b",0);
4460
4461 }
4462
4463 /*-----------------------------------------------------------------*/
4464 /* genMod - generates code for division                            */
4465 /*-----------------------------------------------------------------*/
4466 static void genMod (iCode *ic)
4467 {
4468   operand *left = IC_LEFT(ic);
4469   operand *right = IC_RIGHT(ic);
4470   operand *result= IC_RESULT(ic);  
4471
4472     FENTRY;
4473     
4474     /* assign the amsops */
4475     pic16_aopOp (left,ic,FALSE);
4476     pic16_aopOp (right,ic,FALSE);
4477     pic16_aopOp (result,ic,TRUE);
4478
4479     /* special cases first */
4480     /* both are bits */
4481     if (AOP_TYPE(left) == AOP_CRY &&
4482         AOP_TYPE(right)== AOP_CRY) {
4483         genModbits(left,right,result);
4484         goto release ;
4485     }
4486
4487     /* if both are of size == 1 */
4488     if (AOP_SIZE(left) == 1 &&
4489         AOP_SIZE(right) == 1 ) {
4490         genModOneByte(left,right,result);
4491         goto release ;
4492     }
4493
4494     /* should have been converted to function call */
4495     assert(0);
4496
4497 release :
4498     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4500     pic16_freeAsmop(result,NULL,ic,TRUE); 
4501 }
4502
4503 /*-----------------------------------------------------------------*/
4504 /* genIfxJump :- will create a jump depending on the ifx           */
4505 /*-----------------------------------------------------------------*/
4506 /*
4507   note: May need to add parameter to indicate when a variable is in bit space.
4508 */
4509 static void genIfxJump (iCode *ic, char *jval)
4510 {
4511   FENTRY;
4512   
4513     /* if true label then we jump if condition
4514     supplied is true */
4515     if ( IC_TRUE(ic) ) {
4516
4517         if(strcmp(jval,"a") == 0)
4518           emitSKPZ;
4519         else if (strcmp(jval,"c") == 0)
4520           emitSKPC;
4521         else {
4522           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4523           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4524         }
4525
4526         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4527         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4528
4529     }
4530     else {
4531         /* false label is present */
4532         if(strcmp(jval,"a") == 0)
4533           emitSKPNZ;
4534         else if (strcmp(jval,"c") == 0)
4535           emitSKPNC;
4536         else {
4537           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4538           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4539         }
4540
4541         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4542         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4543
4544     }
4545
4546
4547     /* mark the icode as generated */
4548     ic->generated = 1;
4549 }
4550
4551 #if 0
4552 // not needed ATM
4553
4554 /*-----------------------------------------------------------------*/
4555 /* genSkip                                                         */
4556 /*-----------------------------------------------------------------*/
4557 static void genSkip(iCode *ifx,int status_bit)
4558 {
4559   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4560   if(!ifx)
4561     return;
4562
4563   if ( IC_TRUE(ifx) ) {
4564     switch(status_bit) {
4565     case 'z':
4566       emitSKPNZ;
4567       break;
4568
4569     case 'c':
4570       emitSKPNC;
4571       break;
4572
4573     case 'd':
4574       emitSKPDC;
4575       break;
4576
4577     }
4578
4579     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4580     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4581
4582   } else {
4583
4584     switch(status_bit) {
4585
4586     case 'z':
4587       emitSKPZ;
4588       break;
4589
4590     case 'c':
4591       emitSKPC;
4592       break;
4593
4594     case 'd':
4595       emitSKPDC;
4596       break;
4597     }
4598     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4599     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4600
4601   }
4602
4603 }
4604 #endif
4605
4606 /*-----------------------------------------------------------------*/
4607 /* genSkipc                                                        */
4608 /*-----------------------------------------------------------------*/
4609 static void genSkipc(resolvedIfx *rifx)
4610 {
4611   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4612   
4613   if(!rifx)
4614     return;
4615
4616   if(rifx->condition)
4617     emitSKPC;
4618   else
4619     emitSKPNC;
4620
4621   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4622   rifx->generated = 1;
4623 }
4624
4625 /*-----------------------------------------------------------------*/
4626 /* genSkipz2                                                       */
4627 /*-----------------------------------------------------------------*/
4628 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4629 {
4630   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4631   
4632   if(!rifx)
4633     return;
4634
4635   if( (rifx->condition ^ invert_condition) & 1)
4636     emitSKPZ;
4637   else
4638     emitSKPNZ;
4639
4640   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4641   rifx->generated = 1;
4642 }
4643
4644 #if 0
4645 /*-----------------------------------------------------------------*/
4646 /* genSkipz                                                        */
4647 /*-----------------------------------------------------------------*/
4648 static void genSkipz(iCode *ifx, int condition)
4649 {
4650   if(!ifx)
4651     return;
4652
4653   if(condition)
4654     emitSKPNZ;
4655   else
4656     emitSKPZ;
4657
4658   if ( IC_TRUE(ifx) )
4659     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4660   else
4661     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4662
4663   if ( IC_TRUE(ifx) )
4664     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4665   else
4666     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4667
4668 }
4669 #endif
4670
4671 /*-----------------------------------------------------------------*/
4672 /* genSkipCond                                                     */
4673 /*-----------------------------------------------------------------*/
4674 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4675 {
4676   if(!rifx)
4677     return;
4678
4679   if(rifx->condition)
4680     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4681   else
4682     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4683
4684
4685   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4686   rifx->generated = 1;
4687 }
4688
4689 #if 0
4690 /*-----------------------------------------------------------------*/
4691 /* genChkZeroes :- greater or less than comparison                 */
4692 /*     For each byte in a literal that is zero, inclusive or the   */
4693 /*     the corresponding byte in the operand with W                */
4694 /*     returns true if any of the bytes are zero                   */
4695 /*-----------------------------------------------------------------*/
4696 static int genChkZeroes(operand *op, int lit,  int size)
4697 {
4698
4699   int i;
4700   int flag =1;
4701
4702   while(size--) {
4703     i = (lit >> (size*8)) & 0xff;
4704
4705     if(i==0) {
4706       if(flag) 
4707         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4708       else
4709         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4710       flag = 0;
4711     }
4712   }
4713
4714   return (flag==0);
4715 }
4716 #endif
4717
4718 /*-----------------------------------------------------------------*/
4719 /* genCmp :- greater or less than comparison                       */
4720 /*-----------------------------------------------------------------*/
4721 #if 1
4722                 /* { */
4723       /* original code */
4724 static void genCmp (operand *left,operand *right,
4725                     operand *result, iCode *ifx, int sign)
4726 {
4727   int size; //, offset = 0 ;
4728   unsigned long lit = 0L,i = 0;
4729   resolvedIfx rFalseIfx;
4730   //  resolvedIfx rTrueIfx;
4731   symbol *truelbl;
4732   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4733 /*
4734   if(ifx) {
4735     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4736     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4737   }
4738 */
4739
4740   FENTRY;
4741   
4742   resolveIfx(&rFalseIfx,ifx);
4743   truelbl  = newiTempLabel(NULL);
4744   size = max(AOP_SIZE(left),AOP_SIZE(right));
4745
4746   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4747
4748 #define _swapp
4749
4750   /* if literal is on the right then swap with left */
4751   if ((AOP_TYPE(right) == AOP_LIT)) {
4752     operand *tmp = right ;
4753     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4754     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4755 #ifdef _swapp
4756
4757     lit = (lit - 1) & mask;
4758     right = left;
4759     left = tmp;
4760     rFalseIfx.condition ^= 1;
4761 #endif
4762
4763   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4764     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4765   }
4766
4767
4768   //if(IC_TRUE(ifx) == NULL)
4769   /* if left & right are bit variables */
4770   if (AOP_TYPE(left) == AOP_CRY &&
4771       AOP_TYPE(right) == AOP_CRY ) {
4772     assert (0 && "bit variables used in genCmp");
4773     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4774     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4775   } else {
4776     /* subtract right from left if at the
4777        end the carry flag is set then we know that
4778        left is greater than right */
4779
4780     symbol *lbl  = newiTempLabel(NULL);
4781
4782 #if 0
4783         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4784                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4785 #endif
4786
4787 #ifndef _swapp
4788     if(AOP_TYPE(right) == AOP_LIT) {
4789
4790       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4791
4792       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4793
4794       /* special cases */
4795
4796       if(lit == 0) {
4797
4798         if(sign != 0) 
4799           genSkipCond(&rFalseIfx,left,size-1,7);
4800         else 
4801           /* no need to compare to 0...*/
4802           /* NOTE: this is a de-generate compare that most certainly 
4803            *       creates some dead code. */
4804           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4805
4806         if(ifx) ifx->generated = 1;
4807         return;
4808
4809       }
4810       size--;
4811
4812       if(size == 0) {
4813         //i = (lit >> (size*8)) & 0xff;
4814         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4815         
4816         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4817
4818         i = ((0-lit) & 0xff);
4819         if(sign) {
4820           if( i == 0x81) { 
4821             /* lit is 0x7f, all signed chars are less than
4822              * this except for 0x7f itself */
4823             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4824             genSkipz2(&rFalseIfx,0);
4825           } else {
4826             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4827             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4828             genSkipc(&rFalseIfx);
4829           }
4830
4831         } else {
4832           if(lit == 1) {
4833             genSkipz2(&rFalseIfx,1);
4834           } else {
4835             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4836             genSkipc(&rFalseIfx);
4837           }
4838         }
4839
4840         if(ifx) ifx->generated = 1;
4841         return;
4842       }
4843
4844       /* chars are out of the way. now do ints and longs */
4845
4846
4847       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4848         
4849       /* special cases */
4850
4851       if(sign) {
4852
4853         if(lit == 0) {
4854           genSkipCond(&rFalseIfx,left,size,7);
4855           if(ifx) ifx->generated = 1;
4856           return;
4857         }
4858
4859         if(lit <0x100) {
4860           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4861
4862           //rFalseIfx.condition ^= 1;
4863           //genSkipCond(&rFalseIfx,left,size,7);
4864           //rFalseIfx.condition ^= 1;
4865
4866           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4867           if(rFalseIfx.condition)
4868             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4869           else
4870             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4871
4872           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4873           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4874           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4875
4876           while(size > 1)
4877             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4878
4879           if(rFalseIfx.condition) {
4880             emitSKPZ;
4881             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4882
4883           } else {
4884             emitSKPNZ;
4885           }
4886
4887           genSkipc(&rFalseIfx);
4888           pic16_emitpLabel(truelbl->key);
4889           if(ifx) ifx->generated = 1;
4890           return;
4891
4892         }
4893
4894         if(size == 1) {
4895
4896           if( (lit & 0xff) == 0) {
4897             /* lower byte is zero */
4898             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4899             i = ((lit >> 8) & 0xff) ^0x80;
4900             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4901             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4902             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4903             genSkipc(&rFalseIfx);
4904
4905
4906             if(ifx) ifx->generated = 1;
4907             return;
4908
4909           }
4910         } else {
4911           /* Special cases for signed longs */
4912           if( (lit & 0xffffff) == 0) {
4913             /* lower byte is zero */
4914             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4915             i = ((lit >> 8*3) & 0xff) ^0x80;
4916             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4917             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4918             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4919             genSkipc(&rFalseIfx);
4920
4921
4922             if(ifx) ifx->generated = 1;
4923             return;
4924
4925           }
4926
4927         }
4928
4929
4930         if(lit & (0x80 << (size*8))) {
4931           /* lit is negative */
4932           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4933
4934           //genSkipCond(&rFalseIfx,left,size,7);
4935
4936           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4937
4938           if(rFalseIfx.condition)
4939             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4940           else
4941             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4942
4943
4944         } else {
4945           /* lit is positive */
4946           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4947           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4948           if(rFalseIfx.condition)
4949             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4950           else
4951             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4952
4953         }
4954
4955         /*
4956           This works, but is only good for ints.
4957           It also requires a "known zero" register.
4958           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4959           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4960           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4961           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4962           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4963           genSkipc(&rFalseIfx);
4964
4965           pic16_emitpLabel(truelbl->key);
4966           if(ifx) ifx->generated = 1;
4967           return;
4968         **/
4969           
4970         /* There are no more special cases, so perform a general compare */
4971   
4972         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4973         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4974
4975         while(size--) {
4976
4977           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4978           emitSKPNZ;
4979           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4980         }
4981         //rFalseIfx.condition ^= 1;
4982         genSkipc(&rFalseIfx);
4983
4984         pic16_emitpLabel(truelbl->key);
4985
4986         if(ifx) ifx->generated = 1;
4987         return;
4988
4989
4990       }
4991
4992
4993       /* sign is out of the way. So now do an unsigned compare */
4994       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4995
4996
4997       /* General case - compare to an unsigned literal on the right.*/
4998
4999       i = (lit >> (size*8)) & 0xff;
5000       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5001       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5002       while(size--) {
5003         i = (lit >> (size*8)) & 0xff;
5004
5005         if(i) {
5006           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5007           emitSKPNZ;
5008           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5009         } else {
5010           /* this byte of the lit is zero, 
5011            *if it's not the last then OR in the variable */
5012           if(size)
5013             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5014         }
5015       }
5016
5017
5018       pic16_emitpLabel(lbl->key);
5019 //      pic16_emitpLabel(truelbl->key);
5020       //if(emitFinalCheck)
5021       genSkipc(&rFalseIfx);
5022       if(sign)
5023         pic16_emitpLabel(truelbl->key);
5024
5025       if(ifx) ifx->generated = 1;
5026       return;
5027
5028
5029     }
5030 #endif  // _swapp
5031
5032     if(AOP_TYPE(left) == AOP_LIT) {
5033       //symbol *lbl = newiTempLabel(NULL);
5034
5035       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5036
5037
5038       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5039
5040       /* Special cases */
5041       if((lit == 0) && (sign == 0)){
5042
5043         size--;
5044         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5045         while(size) 
5046           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5047
5048         genSkipz2(&rFalseIfx,0);
5049         if(ifx) ifx->generated = 1;
5050         return;
5051       }
5052
5053       if(size==1) {
5054         /* Special cases */
5055         lit &= 0xff;
5056         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5057           /* degenerate compare can never be true */
5058           if(rFalseIfx.condition == 0)
5059             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5060
5061           if(ifx) ifx->generated = 1;
5062           return;
5063         }
5064
5065         if(sign) {
5066           /* signed comparisons to a literal byte */
5067
5068           int lp1 = (lit+1) & 0xff;
5069
5070           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5071           switch (lp1) {
5072           case 0:
5073             rFalseIfx.condition ^= 1;
5074             genSkipCond(&rFalseIfx,right,0,7);
5075             break;
5076           case 0x7f:
5077             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5078             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5079             genSkipz2(&rFalseIfx,1);
5080             break;
5081           default:
5082             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5083             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5084             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5085             rFalseIfx.condition ^= 1;
5086             genSkipc(&rFalseIfx);
5087             break;
5088           }
5089         } else {
5090           /* unsigned comparisons to a literal byte */
5091
5092           switch(lit & 0xff ) {
5093           case 0:
5094             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5095             genSkipz2(&rFalseIfx,0);
5096             break;
5097           case 0x7f:
5098             rFalseIfx.condition ^= 1;
5099             genSkipCond(&rFalseIfx,right,0,7);
5100             break;
5101
5102           default:
5103             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5104             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5105             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5106             rFalseIfx.condition ^= 1;
5107             if (AOP_TYPE(result) == AOP_CRY)
5108               genSkipc(&rFalseIfx);
5109             else {
5110               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5111               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5112             }         
5113             break;
5114           }
5115         }
5116
5117         if(ifx) ifx->generated = 1;
5118         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5119                 goto check_carry;
5120         return;
5121
5122       } else {
5123
5124         /* Size is greater than 1 */
5125
5126         if(sign) {
5127           int lp1 = lit+1;
5128
5129           size--;
5130
5131           if(lp1 == 0) {
5132             /* this means lit = 0xffffffff, or -1 */
5133
5134
5135             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5136             rFalseIfx.condition ^= 1;
5137             genSkipCond(&rFalseIfx,right,size,7);
5138             if(ifx) ifx->generated = 1;
5139
5140             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5141               goto check_carry;
5142
5143             return;
5144           }
5145
5146           if(lit == 0) {
5147             int s = size;
5148
5149             if(rFalseIfx.condition) {
5150               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5151               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5152             }
5153
5154             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5155             while(size--)
5156               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5157
5158
5159             emitSKPZ;
5160             if(rFalseIfx.condition) {
5161               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5162               pic16_emitpLabel(truelbl->key);
5163             }else {
5164               rFalseIfx.condition ^= 1;
5165               genSkipCond(&rFalseIfx,right,s,7);
5166             }
5167
5168             if(ifx) ifx->generated = 1;
5169
5170             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5171               goto check_carry;
5172
5173             return;
5174           }
5175
5176           if((size == 1) &&  (0 == (lp1&0xff))) {
5177             /* lower byte of signed word is zero */
5178             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5179             i = ((lp1 >> 8) & 0xff) ^0x80;
5180             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5181             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5182             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5183
5184             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5185               emitTOGC;
5186               if(ifx) ifx->generated = 1;
5187               goto check_carry;
5188             } else {
5189               rFalseIfx.condition ^= 1;
5190               genSkipc(&rFalseIfx);
5191               if(ifx) ifx->generated = 1;
5192             }
5193
5194             return;
5195           }
5196
5197           if(lit & (0x80 << (size*8))) {
5198             /* Lit is less than zero */
5199             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5200             //rFalseIfx.condition ^= 1;
5201             //genSkipCond(&rFalseIfx,left,size,7);
5202             //rFalseIfx.condition ^= 1;
5203             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5204             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5205
5206             if(rFalseIfx.condition)
5207               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5208             else
5209               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5210
5211
5212           } else {
5213             /* Lit is greater than or equal to zero */
5214             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5215             //rFalseIfx.condition ^= 1;
5216             //genSkipCond(&rFalseIfx,right,size,7);
5217             //rFalseIfx.condition ^= 1;
5218
5219             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5220             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5221
5222             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5223             if(rFalseIfx.condition)
5224               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5225             else
5226               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5227
5228           }
5229
5230           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5231           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5232
5233           while(size--) {
5234
5235             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5236             emitSKPNZ;
5237             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5238           }
5239           rFalseIfx.condition ^= 1;
5240           //rFalseIfx.condition = 1;
5241           genSkipc(&rFalseIfx);
5242
5243           pic16_emitpLabel(truelbl->key);
5244
5245           if(ifx) ifx->generated = 1;
5246
5247
5248           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5249             goto check_carry;
5250
5251           return;
5252           // end of if (sign)
5253         } else {
5254
5255           /* compare word or long to an unsigned literal on the right.*/
5256
5257
5258           size--;
5259           if(lit < 0xff) {
5260             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5261             switch (lit) {
5262             case 0:
5263               break; /* handled above */
5264 /*
5265             case 0xff:
5266               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5267               while(size--)
5268                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5269               genSkipz2(&rFalseIfx,0);
5270               break;
5271 */
5272             default:
5273               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5274               while(--size)
5275                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5276
5277               emitSKPZ;
5278               if(rFalseIfx.condition)
5279                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5280               else
5281                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5282
5283
5284               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5285               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5286
5287               rFalseIfx.condition ^= 1;
5288               genSkipc(&rFalseIfx);
5289             }
5290
5291             pic16_emitpLabel(truelbl->key);
5292
5293             if(ifx) ifx->generated = 1;
5294
5295             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5296               goto check_carry;
5297
5298             return;
5299           }
5300
5301
5302           lit++;
5303           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5304           i = (lit >> (size*8)) & 0xff;
5305
5306           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5307           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5308
5309           while(size--) {
5310             i = (lit >> (size*8)) & 0xff;
5311
5312             if(i) {
5313               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5314               emitSKPNZ;
5315               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5316             } else {
5317               /* this byte of the lit is zero, 
5318                * if it's not the last then OR in the variable */
5319               if(size)
5320                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5321             }
5322           }
5323
5324
5325           pic16_emitpLabel(lbl->key);
5326
5327           rFalseIfx.condition ^= 1;
5328
5329           genSkipc(&rFalseIfx);
5330         }
5331
5332         if(sign)
5333           pic16_emitpLabel(truelbl->key);
5334         if(ifx) ifx->generated = 1;
5335
5336             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5337               goto check_carry;
5338
5339         return;
5340       }
5341     }
5342     /* Compare two variables */
5343
5344     DEBUGpic16_emitcode(";sign","%d",sign);
5345
5346     size--;
5347     if(sign) {
5348       /* Sigh. thus sucks... */
5349       if(size) {
5350         pCodeOp *pctemp;
5351         
5352         pctemp = pic16_popGetTempReg(1);
5353         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5354         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5355         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5356         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5357         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5358         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5359         pic16_popReleaseTempReg(pctemp, 1);
5360       } else {
5361         /* Signed char comparison */
5362         /* Special thanks to Nikolai Golovchenko for this snippet */
5363         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5364         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5365         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5366         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5367         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5368         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5369
5370         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5371         genSkipc(&rFalseIfx);
5372           
5373         if(ifx) ifx->generated = 1;
5374
5375             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5376               goto check_carry;
5377
5378         return;
5379       }
5380
5381     } else {
5382
5383       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5384       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5385     }
5386
5387
5388     /* The rest of the bytes of a multi-byte compare */
5389     while (size) {
5390
5391       emitSKPZ;
5392       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5393       size--;
5394
5395       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5396       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5397
5398
5399     }
5400
5401     pic16_emitpLabel(lbl->key);
5402
5403     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5404     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5405         (AOP_TYPE(result) == AOP_REG)) {
5406       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5407       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5408     } else {
5409       genSkipc(&rFalseIfx);
5410     }         
5411     //genSkipc(&rFalseIfx);
5412     if(ifx) ifx->generated = 1;
5413
5414
5415             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5416               goto check_carry;
5417
5418     return;
5419
5420   }
5421
5422 check_carry:
5423   if ((AOP_TYPE(result) != AOP_CRY) 
5424         && AOP_SIZE(result)) {
5425     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5426
5427     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5428
5429     pic16_outBitC(result);
5430   } else {
5431     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5432     /* if the result is used in the next
5433        ifx conditional branch then generate
5434        code a little differently */
5435     if (ifx )
5436       genIfxJump (ifx,"c");
5437     else
5438       pic16_outBitC(result);
5439     /* leave the result in acc */
5440   }
5441
5442 }
5443
5444 #else   /* old version of genCmp() */   /* } else { */
5445
5446 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5447 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5448         operand *result, int offset, int invert_op)
5449 {
5450   /* add code here */
5451   
5452   /* check condition, > or < ?? */
5453   if(rIfx->condition != 0)invert_op ^= 1;
5454   
5455   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5456
5457   if(!ifx)invert_op ^= 1;
5458
5459   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5460       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5461   
5462   /* do selection */
5463   if(!invert_op)return POC_CPFSGT;
5464   else return POC_CPFSLT;
5465 }
5466
5467 static int compareAopfirstpass=1;
5468
5469 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5470             operand *oper, int offset, operand *result,
5471             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5472             symbol *tlbl)
5473 {
5474   int op;
5475   symbol *truelbl;
5476
5477   /* invert if there is a result to be loaded, in order to fit,
5478    * SETC/CLRC sequence */
5479   if(AOP_SIZE(result))invert_op ^= 1;
5480
5481 //  if(sign && !offset)invert_op ^= 1;
5482   
5483 //  if(sign)invert_op ^= 1;
5484   
5485   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5486
5487   if(AOP_SIZE(result) && compareAopfirstpass) {
5488     if(!ifx) {
5489       if(pcop2)
5490         pic16_emitpcode(POC_SETF, pcop2);
5491       else
5492         emitSETC;
5493     } else {
5494       if(pcop2)
5495         pic16_emitpcode(POC_CLRF, pcop2);
5496       else
5497         emitCLRC;
5498     }
5499   }
5500
5501   compareAopfirstpass = 0;
5502
5503       /* there is a bug when comparing operands with size > 1,
5504        * because higher bytes can be equal and test should be performed
5505        * to the next lower byte, current algorithm, considers operands
5506        * inequal in these cases! -- VR 20041107 */
5507
5508     
5509   if(pcop)
5510     pic16_emitpcode(op, pcop);
5511   else
5512     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5513
5514
5515   if((!sign || !offset) && AOP_SIZE(result)) {
5516     if(!ifx) {
5517       if(pcop2)
5518         pic16_emitpcode(POC_CLRF, pcop2);
5519         else
5520         emitCLRC;
5521     } else {
5522       if(pcop2)
5523         pic16_emitpcode(POC_SETF, pcop2);
5524       else
5525         emitSETC;
5526     }
5527     
5528     /* don't emit final branch (offset == 0) */
5529     if(offset) {
5530
5531       if(pcop2)
5532         pic16_emitpcode(POC_RRCF, pcop2);
5533
5534       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5535     }
5536   } else {
5537     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5538       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5539             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5540
5541       truelbl = newiTempLabel( NULL );
5542       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5543       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5544         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5545       else
5546         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5547       pic16_emitpLabel(truelbl->key);
5548     } else {
5549       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5550     }
5551   }
5552 }
5553
5554
5555   
5556
5557 #if 1   /* { */
5558 static void genCmp (operand *left, operand *right,
5559                     operand *result, iCode *ifx, int sign)
5560 {
5561   int size, cmpop=1;
5562   long lit = 0L;
5563   resolvedIfx rFalseIfx;
5564   symbol *falselbl, *tlbl;
5565
5566     FENTRY;
5567     
5568     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5569
5570     resolveIfx(&rFalseIfx, ifx);
5571     size = max(AOP_SIZE(left), AOP_SIZE(right));
5572     
5573     /* if left & right are bit variables */
5574     if(AOP_TYPE(left) == AOP_CRY
5575       && AOP_TYPE(right) == AOP_CRY ) {
5576
5577         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5578         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5579         
5580         werror(W_POSSBUG2, __FILE__, __LINE__);
5581         exit(-1);
5582     }
5583     
5584     /* if literal is on the right then swap with left */
5585     if((AOP_TYPE(right) == AOP_LIT)) {
5586       operand *tmp = right ;
5587 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5588
5589         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5590
5591 //      lit = (lit - 1) & mask;
5592         right = left;
5593         left = tmp;
5594         rFalseIfx.condition ^= 1;               /* reverse compare */
5595     } else
5596     if ((AOP_TYPE(left) == AOP_LIT)) {
5597       /* float compares are handled by support functions */
5598       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5599     }
5600
5601     /* actual comparing algorithm */
5602 //    size = AOP_SIZE( right );
5603
5604     falselbl = newiTempLabel( NULL );
5605     if(AOP_TYPE(left) == AOP_LIT) {
5606       /* compare to literal */
5607       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5608       
5609       if(sign) {
5610         pCodeOp *pct, *pct2;
5611         symbol *tlbl1;
5612
5613         /* signed compare */
5614         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5615
5616         pct = pic16_popCopyReg(&pic16_pc_prodl);
5617         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5618         tlbl = newiTempLabel( NULL );
5619         
5620         /* first compare signs:
5621          *  a. if both are positive, compare just like unsigned
5622          *  b. if both are negative, invert cmpop, compare just like unsigned
5623          *  c. if different signs, determine the result directly */
5624
5625         size--;
5626
5627 #if 1
5628         /* { */
5629         tlbl1 = newiTempLabel( NULL );
5630 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5631
5632         if(lit > 0) {
5633
5634           /* literal is zero or positive:
5635            *  a. if carry is zero, too, continue compare,
5636            *  b. if carry is set, then continue depending on cmpop ^ condition:
5637            *    1. '<' return false (literal < variable),
5638            *    2. '>' return true (literal > variable) */
5639 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5640           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5641           
5642           
5643           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5644           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5645         } else 
5646         if(lit < 0) {
5647           
5648           /* literal is negative:
5649            *  a. if carry is set, too, continue compare,
5650            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5651            *    1. '<' return true (literal < variable),
5652            *    2. '>' return false (literal > variable) */
5653 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5654           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5655           
5656           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5657           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5658         }
5659 #if 1
5660         else {
5661           /* lit == 0 */
5662           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5663           
5664           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5665           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5666         }
5667 #endif
5668         
5669         
5670         pic16_emitpLabel( tlbl1->key );
5671 #endif  /* } */
5672
5673         compareAopfirstpass=1;
5674 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5675 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5676 //        pic16_emitpcode(POC_MOVWF, pct);
5677
5678 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5679         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5680 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5681         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5682
5683         /* generic case */        
5684           while( size-- ) {
5685 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5686 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5687 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5688 //            pic16_emitpcode(POC_MOVWF, pct);
5689
5690 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5691             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5692             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5693 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5694 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5695           }
5696 //        }
5697         
5698         if(ifx)ifx->generated = 1;
5699
5700         if(AOP_SIZE(result)) {
5701           pic16_emitpLabel(tlbl->key);
5702           pic16_emitpLabel(falselbl->key);
5703           pic16_outBitOp( result, pct2 );
5704         } else {
5705           pic16_emitpLabel(tlbl->key);
5706         }
5707       } else {
5708
5709
5710         /* unsigned compare */      
5711         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5712     
5713         compareAopfirstpass=1;
5714         while(size--) {
5715           
5716           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5717           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5718
5719         }
5720
5721         if(ifx)ifx->generated = 1;
5722
5723
5724         if(AOP_SIZE(result)) {
5725           pic16_emitpLabel(falselbl->key);
5726           pic16_outBitC( result );
5727         }
5728
5729       }
5730     } else {
5731       /* compare registers */
5732       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5733
5734
5735       if(sign) {
5736         pCodeOp *pct, *pct2;
5737         
5738         /* signed compare */
5739         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5740
5741         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
5742         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
5743         tlbl = newiTempLabel( NULL );
5744         
5745         compareAopfirstpass=1;
5746
5747         size--;
5748         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5749 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5750         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5751         pic16_emitpcode(POC_MOVWF, pct);
5752
5753         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5754 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5755         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5756
5757         /* WREG already holds left + 0x80 */
5758         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5759         
5760         while( size-- ) {
5761           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5762 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5763           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5764           pic16_emitpcode(POC_MOVWF, pct);
5765                 
5766           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5767 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5768           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5769
5770           /* WREG already holds left + 0x80 */
5771           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5772 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5773         }
5774         
5775         if(ifx)ifx->generated = 1;
5776
5777         if(AOP_SIZE(result)) {
5778           pic16_emitpLabel(tlbl->key);
5779           pic16_emitpLabel(falselbl->key);
5780           pic16_outBitOp( result, pct2 );
5781         } else {
5782           pic16_emitpLabel(tlbl->key);
5783         }
5784
5785       } else {
5786         /* unsigned compare */      
5787         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5788
5789         compareAopfirstpass=1;
5790         while(size--) {
5791           
5792           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5793           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5794
5795         }
5796
5797         if(ifx)ifx->generated = 1;
5798         if(AOP_SIZE(result)) {
5799
5800           pic16_emitpLabel(falselbl->key);
5801           pic16_outBitC( result );
5802         }
5803
5804       }
5805     }
5806 }
5807
5808 #else    /* } else { */
5809
5810 /* new version of genCmp -- VR 20041012 */
5811 static void genCmp (operand *left,operand *right,
5812                     operand *result, iCode *ifx, int sign)
5813 {
5814   int size; //, offset = 0 ;
5815   unsigned long lit = 0L,i = 0;
5816   resolvedIfx rFalseIfx;
5817   int willCheckCarry=0;
5818   //  resolvedIfx rTrueIfx;
5819   symbol *truelbl;
5820
5821     FENTRY;
5822   
5823   /* General concept:
5824    * subtract right from left if at the end the carry flag is set then we
5825    * know that left is greater than right */
5826             
5827   resolveIfx(&rFalseIfx,ifx);
5828   truelbl  = newiTempLabel(NULL);
5829   size = max(AOP_SIZE(left),AOP_SIZE(right));
5830
5831   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5832
5833   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5834    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5835   
5836
5837   /* if literal is on the right then swap with left */
5838   if ((AOP_TYPE(right) == AOP_LIT)) {
5839     operand *tmp = right ;
5840     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5841
5842       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5843
5844 //      lit = (lit - 1) & mask;
5845       right = left;
5846       left = tmp;
5847       rFalseIfx.condition ^= 1;         /* reverse compare */
5848   } else
5849   if ((AOP_TYPE(left) == AOP_LIT)) {
5850     /* float compares are handled by support functions */
5851     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5852   }
5853
5854
5855   //if(IC_TRUE(ifx) == NULL)
5856   /* if left & right are bit variables */
5857   if (AOP_TYPE(left) == AOP_CRY &&
5858       AOP_TYPE(right) == AOP_CRY ) {
5859
5860     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5861     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5862
5863   } else {
5864     symbol *lbl  = newiTempLabel(NULL);
5865
5866     if(AOP_TYPE(left) == AOP_LIT) {
5867       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5868
5869       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5870         willCheckCarry = 1;
5871       else willCheckCarry = 0;
5872
5873       /* Special cases */
5874       if((lit == 0) && (sign == 0)) {
5875         /* unsigned compare to 0 */
5876         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5877         
5878         size--;
5879         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5880         while(size) 
5881           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5882
5883         genSkipz2(&rFalseIfx,0);
5884         if(ifx)ifx->generated = 1;
5885         return;
5886       }
5887
5888       if(size==1) {
5889         /* Special cases */
5890         lit &= 0xff;
5891         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5892           /* degenerate compare can never be true */
5893           if(rFalseIfx.condition == 0)
5894             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5895
5896           if(ifx) ifx->generated = 1;
5897           return;
5898         }
5899
5900         if(sign) {
5901           /* signed comparisons to a literal byte */
5902           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5903
5904           int lp1 = (lit+1) & 0xff;
5905
5906           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5907           switch (lp1) {
5908           case 0:
5909             rFalseIfx.condition ^= 1;
5910             genSkipCond(&rFalseIfx,right,0,7);
5911             break;
5912           case 0x7f:
5913             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5914             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5915             genSkipz2(&rFalseIfx,1);
5916             break;
5917           default:
5918             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5919             
5920             if(rFalseIfx.condition)
5921               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5922             else
5923               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5924
5925             if(willCheckCarry) {
5926               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5927               else { emitSETC; emitCLRC; }
5928               
5929             } else {
5930               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5931             }              
5932                       
5933 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5934             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5935             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5936             rFalseIfx.condition ^= 1;
5937             genSkipc(&rFalseIfx);
5938 */
5939             break;
5940           }
5941         } else {
5942           /* unsigned comparisons to a literal byte */
5943           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5944
5945           switch(lit & 0xff ) {
5946                           /* special cases */
5947           case 0:
5948             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5949             genSkipz2(&rFalseIfx,0);
5950             break;
5951           case 0x7f:
5952             rFalseIfx.condition ^= 1;
5953             genSkipCond(&rFalseIfx,right,0,7);
5954             break;
5955           default:
5956             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5957             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5958             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5959             rFalseIfx.condition ^= 1;
5960             if (AOP_TYPE(result) == AOP_CRY)
5961               genSkipc(&rFalseIfx);
5962             else {
5963               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5964               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5965             }         
5966             break;
5967           }
5968         }
5969
5970         if(ifx) ifx->generated = 1;
5971         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5972                 goto check_carry;
5973         return;
5974
5975       } else {
5976
5977         /* Size is greater than 1 */
5978
5979         if(sign) {
5980           int lp1 = lit+1;
5981
5982           size--;
5983
5984           if(lp1 == 0) {
5985             /* this means lit = 0xffffffff, or -1 */
5986
5987
5988             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5989             rFalseIfx.condition ^= 1;
5990             genSkipCond(&rFalseIfx,right,size,7);
5991             if(ifx) ifx->generated = 1;
5992             return;
5993           }
5994
5995           if(lit == 0) {
5996             int s = size;
5997
5998             if(rFalseIfx.condition) {
5999               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6000               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6001             }
6002
6003             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6004             while(size--)
6005               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6006
6007
6008             emitSKPZ;
6009             if(rFalseIfx.condition) {
6010               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6011               pic16_emitpLabel(truelbl->key);
6012             }else {
6013               rFalseIfx.condition ^= 1;
6014               genSkipCond(&rFalseIfx,right,s,7);
6015             }
6016
6017             if(ifx) ifx->generated = 1;
6018             return;
6019           }
6020
6021           if((size == 1) &&  (0 == (lp1&0xff))) {
6022             /* lower byte of signed word is zero */
6023             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6024             i = ((lp1 >> 8) & 0xff) ^0x80;
6025             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6026             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6027             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6028             rFalseIfx.condition ^= 1;
6029             genSkipc(&rFalseIfx);
6030
6031
6032             if(ifx) ifx->generated = 1;
6033             return;
6034           }
6035
6036           if(lit & (0x80 << (size*8))) {
6037             /* Lit is less than zero */
6038             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6039             //rFalseIfx.condition ^= 1;
6040             //genSkipCond(&rFalseIfx,left,size,7);
6041             //rFalseIfx.condition ^= 1;
6042             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6043             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6044
6045             if(rFalseIfx.condition)
6046               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6047             else
6048               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6049
6050
6051           } else {
6052             /* Lit is greater than or equal to zero */
6053             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6054             //rFalseIfx.condition ^= 1;
6055             //genSkipCond(&rFalseIfx,right,size,7);
6056             //rFalseIfx.condition ^= 1;
6057
6058             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6059             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6060
6061             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6062             if(rFalseIfx.condition)
6063               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6064             else
6065               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6066
6067           }
6068
6069
6070           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6071           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6072
6073           while(size--) {
6074
6075             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6076             emitSKPNZ;
6077             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6078           }
6079           rFalseIfx.condition ^= 1;
6080           //rFalseIfx.condition = 1;
6081           genSkipc(&rFalseIfx);
6082
6083           pic16_emitpLabel(truelbl->key);
6084
6085           if(ifx) ifx->generated = 1;
6086           return;
6087           // end of if (sign)
6088         } else {
6089
6090           /* compare word or long to an unsigned literal on the right.*/
6091
6092
6093           size--;
6094           if(lit < 0xff) {
6095             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6096             switch (lit) {
6097             case 0:
6098               break; /* handled above */
6099 /*
6100             case 0xff:
6101               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6102               while(size--)
6103                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6104               genSkipz2(&rFalseIfx,0);
6105               break;
6106 */
6107             default:
6108               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6109               while(--size)
6110                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6111
6112               emitSKPZ;
6113               if(rFalseIfx.condition)
6114                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6115               else
6116                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6117
6118
6119               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6120               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6121
6122               rFalseIfx.condition ^= 1;
6123               genSkipc(&rFalseIfx);
6124             }
6125
6126             pic16_emitpLabel(truelbl->key);
6127
6128             if(ifx) ifx->generated = 1;
6129             return;
6130           }
6131
6132
6133           lit++;
6134           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6135           i = (lit >> (size*8)) & 0xff;
6136
6137           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6138           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6139
6140           while(size--) {
6141             i = (lit >> (size*8)) & 0xff;
6142
6143             if(i) {
6144               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6145               emitSKPNZ;
6146               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6147             } else {
6148               /* this byte of the lit is zero, 
6149                * if it's not the last then OR in the variable */
6150               if(size)
6151                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6152             }
6153           }
6154
6155
6156           pic16_emitpLabel(lbl->key);
6157
6158           rFalseIfx.condition ^= 1;
6159
6160           genSkipc(&rFalseIfx);
6161         }
6162
6163         if(sign)
6164           pic16_emitpLabel(truelbl->key);
6165         if(ifx) ifx->generated = 1;
6166         return;
6167       }
6168     }
6169     /* Compare two variables */
6170
6171     DEBUGpic16_emitcode(";sign","%d",sign);
6172
6173     size--;
6174     if(sign) {
6175       /* Sigh. thus sucks... */
6176       if(size) {
6177         pCodeOp *pctemp;
6178         
6179         pctemp = pic16_popGetTempReg(1);
6180         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6181         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6182         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6183         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6184         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6185         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6186         pic16_popReleaseTempReg(pctemp, 1);
6187       } else {
6188         /* Signed char comparison */
6189         /* Special thanks to Nikolai Golovchenko for this snippet */
6190         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6191         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6192         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6193         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6194         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6195         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6196
6197         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6198         genSkipc(&rFalseIfx);
6199           
6200         if(ifx) ifx->generated = 1;
6201         return;
6202       }
6203
6204     } else {
6205
6206       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6207       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6208     }
6209
6210
6211     /* The rest of the bytes of a multi-byte compare */
6212     while (size) {
6213
6214       emitSKPZ;
6215       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6216       size--;
6217
6218       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6219       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6220
6221
6222     }
6223
6224     pic16_emitpLabel(lbl->key);
6225
6226     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6227     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6228         (AOP_TYPE(result) == AOP_REG)) {
6229       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6230       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6231     } else {
6232       genSkipc(&rFalseIfx);
6233     }         
6234     //genSkipc(&rFalseIfx);
6235     if(ifx) ifx->generated = 1;
6236
6237     return;
6238
6239   }
6240
6241 check_carry:
6242   if ((AOP_TYPE(result) != AOP_CRY) 
6243         && AOP_SIZE(result)) {
6244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6245
6246     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6247
6248     pic16_outBitC(result);
6249   } else {
6250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6251     /* if the result is used in the next
6252        ifx conditional branch then generate
6253        code a little differently */
6254     if (ifx )
6255       genIfxJump (ifx,"c");
6256     else
6257       pic16_outBitC(result);
6258     /* leave the result in acc */
6259   }
6260
6261 }
6262 #endif  /* } */
6263
6264
6265 #endif  /* } */
6266
6267
6268
6269 /*-----------------------------------------------------------------*/
6270 /* genCmpGt :- greater than comparison                             */
6271 /*-----------------------------------------------------------------*/
6272 static void genCmpGt (iCode *ic, iCode *ifx)
6273 {
6274   operand *left, *right, *result;
6275   sym_link *letype , *retype;
6276   int sign ;
6277
6278     FENTRY;
6279     
6280     left = IC_LEFT(ic);
6281     right= IC_RIGHT(ic);
6282     result = IC_RESULT(ic);
6283
6284     letype = getSpec(operandType(left));
6285     retype =getSpec(operandType(right));
6286     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6287     /* assign the amsops */
6288     pic16_aopOp (left,ic,FALSE);
6289     pic16_aopOp (right,ic,FALSE);
6290     pic16_aopOp (result,ic,TRUE);
6291
6292     genCmp(right, left, result, ifx, sign);
6293
6294     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296     pic16_freeAsmop(result,NULL,ic,TRUE); 
6297 }
6298
6299 /*-----------------------------------------------------------------*/
6300 /* genCmpLt - less than comparisons                                */
6301 /*-----------------------------------------------------------------*/
6302 static void genCmpLt (iCode *ic, iCode *ifx)
6303 {
6304   operand *left, *right, *result;
6305   sym_link *letype , *retype;
6306   int sign ;
6307
6308     FENTRY;
6309
6310     left = IC_LEFT(ic);
6311     right= IC_RIGHT(ic);
6312     result = IC_RESULT(ic);
6313
6314     letype = getSpec(operandType(left));
6315     retype =getSpec(operandType(right));
6316     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6317
6318     /* assign the amsops */
6319     pic16_aopOp (left,ic,FALSE);
6320     pic16_aopOp (right,ic,FALSE);
6321     pic16_aopOp (result,ic,TRUE);
6322
6323     genCmp(left, right, result, ifx, sign);
6324
6325     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6327     pic16_freeAsmop(result,NULL,ic,TRUE); 
6328 }
6329
6330 #if 0
6331 // not needed ATM
6332 // FIXME reenable literal optimisation when the pic16 port is stable
6333
6334 /*-----------------------------------------------------------------*/
6335 /* genc16bit2lit - compare a 16 bit value to a literal             */
6336 /*-----------------------------------------------------------------*/
6337 static void genc16bit2lit(operand *op, int lit, int offset)
6338 {
6339   int i;
6340
6341   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6342   if( (lit&0xff) == 0) 
6343     i=1;
6344   else
6345     i=0;
6346
6347   switch( BYTEofLONG(lit,i)) { 
6348   case 0:
6349     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350     break;
6351   case 1:
6352     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6353     break;
6354   case 0xff:
6355     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6356     break;
6357   default:
6358     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6360   }
6361
6362   i ^= 1;
6363
6364   switch( BYTEofLONG(lit,i)) { 
6365   case 0:
6366     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6367     break;
6368   case 1:
6369     emitSKPNZ;
6370     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6371     break;
6372   case 0xff:
6373     emitSKPNZ;
6374     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   default:
6377     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6380
6381   }
6382
6383 }
6384 #endif
6385
6386 #if 0
6387 // not needed ATM
6388 /*-----------------------------------------------------------------*/
6389 /* gencjneshort - compare and jump if not equal                    */
6390 /*-----------------------------------------------------------------*/
6391 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6392 {
6393   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6394   int offset = 0;
6395   int res_offset = 0;  /* the result may be a different size then left or right */
6396   int res_size = AOP_SIZE(result);
6397   resolvedIfx rIfx;
6398   symbol *lbl, *lbl_done;
6399
6400   unsigned long lit = 0L;
6401   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6402
6403   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6404   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6405   if(result)
6406     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6407   resolveIfx(&rIfx,ifx);
6408   lbl =  newiTempLabel(NULL);
6409   lbl_done =  newiTempLabel(NULL);
6410
6411
6412   /* if the left side is a literal or 
6413      if the right is in a pointer register and left 
6414      is not */
6415   if ((AOP_TYPE(left) == AOP_LIT) || 
6416       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6417     operand *t = right;
6418     right = left;
6419     left = t;
6420   }
6421   if(AOP_TYPE(right) == AOP_LIT)
6422     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6423
6424   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6425     preserve_result = 1;
6426
6427   if(result && !preserve_result)
6428     {
6429       int i;
6430       for(i = 0; i < AOP_SIZE(result); i++)
6431         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6432     }
6433
6434
6435   /* if the right side is a literal then anything goes */
6436   if (AOP_TYPE(right) == AOP_LIT &&
6437       AOP_TYPE(left) != AOP_DIR ) {
6438     switch(size) {
6439     case 2:
6440       genc16bit2lit(left, lit, 0);
6441       emitSKPZ;
6442       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443       break;
6444     default:
6445       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6446       while (size--) {
6447         if(lit & 0xff) {
6448           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6450         } else {
6451           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6452         }
6453
6454         emitSKPZ;
6455         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6456         offset++;
6457         if(res_offset < res_size-1)
6458           res_offset++;
6459         lit >>= 8;
6460       }
6461       break;
6462     }
6463   }
6464
6465   /* if the right side is in a register or in direct space or
6466      if the left is a pointer register & right is not */    
6467   else if (AOP_TYPE(right) == AOP_REG ||
6468            AOP_TYPE(right) == AOP_DIR || 
6469            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6470            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6471     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6472     int lbl_key = lbl->key;
6473
6474     if(result) {
6475       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6476       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6477     }else {
6478       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6479       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6480               __FUNCTION__,__LINE__);
6481       return;
6482     }
6483    
6484 /*     switch(size) { */
6485 /*     case 2: */
6486 /*       genc16bit2lit(left, lit, 0); */
6487 /*       emitSKPNZ; */
6488 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6489 /*       break; */
6490 /*     default: */
6491     while (size--) {
6492       int emit_skip=1;
6493       if((AOP_TYPE(left) == AOP_DIR) && 
6494          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6495
6496         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6498
6499       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6500             
6501         switch (lit & 0xff) {
6502         case 0:
6503           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504           break;
6505         case 1:
6506           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6507           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6509           emit_skip=0;
6510           break;
6511         case 0xff:
6512           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6516           emit_skip=0;
6517           break;
6518         default:
6519           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6521         }
6522         lit >>= 8;
6523
6524       } else {
6525         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6526       }
6527       if(emit_skip) {
6528         if(AOP_TYPE(result) == AOP_CRY) {
6529           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6530           if(rIfx.condition)
6531             emitSKPNZ;
6532           else
6533             emitSKPZ;
6534           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6535         } else {
6536           /* fix me. probably need to check result size too */
6537           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6538           if(rIfx.condition)
6539             emitSKPZ;
6540           else
6541             emitSKPNZ;
6542           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6543           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6544         }
6545         if(ifx)
6546           ifx->generated=1;
6547       }
6548       emit_skip++;
6549       offset++;
6550       if(res_offset < res_size-1)
6551         res_offset++;
6552     }
6553 /*       break; */
6554 /*     } */
6555   } else if(AOP_TYPE(right) == AOP_REG &&
6556             AOP_TYPE(left) != AOP_DIR){
6557
6558     while(size--) {
6559       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6560       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6561       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6562       if(rIfx.condition)
6563         emitSKPNZ;
6564       else
6565         emitSKPZ;
6566       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6567       offset++;
6568       if(res_offset < res_size-1)
6569         res_offset++;
6570     }
6571       
6572   }else{
6573     /* right is a pointer reg need both a & b */
6574     while(size--) {
6575       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6576       if(strcmp(l,"b"))
6577         pic16_emitcode("mov","b,%s",l);
6578       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6579       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6580       offset++;
6581     }
6582   }
6583
6584   if(result && preserve_result)
6585     {
6586       int i;
6587       for(i = 0; i < AOP_SIZE(result); i++)
6588         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6589     }
6590
6591   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6592
6593   if(result && preserve_result)
6594     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6595
6596   if(!rIfx.condition)
6597     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6598
6599   pic16_emitpLabel(lbl->key);
6600
6601   if(result && preserve_result)
6602     {
6603       int i;
6604       for(i = 0; i < AOP_SIZE(result); i++)
6605         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6606
6607       pic16_emitpLabel(lbl_done->key);
6608    }
6609
6610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6611
6612   if(ifx)
6613     ifx->generated = 1;
6614 }
6615 #endif
6616
6617 #if 0
6618 /*-----------------------------------------------------------------*/
6619 /* gencjne - compare and jump if not equal                         */
6620 /*-----------------------------------------------------------------*/
6621 static void gencjne(operand *left, operand *right, iCode *ifx)
6622 {
6623     symbol *tlbl  = newiTempLabel(NULL);
6624
6625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6626     gencjneshort(left, right, lbl);
6627
6628     pic16_emitcode("mov","a,%s",one);
6629     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6630     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6631     pic16_emitcode("clr","a");
6632     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6633
6634     pic16_emitpLabel(lbl->key);
6635     pic16_emitpLabel(tlbl->key);
6636
6637 }
6638 #endif
6639
6640
6641 /*-----------------------------------------------------------------*/
6642 /* is_LitOp - check if operand has to be treated as literal        */
6643 /*-----------------------------------------------------------------*/
6644 static bool is_LitOp(operand *op)
6645 {
6646   return ((AOP_TYPE(op) == AOP_LIT)
6647       || ( (AOP_TYPE(op) == AOP_PCODE)
6648           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6649               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6650 }
6651
6652 /*-----------------------------------------------------------------*/
6653 /* is_LitAOp - check if operand has to be treated as literal        */
6654 /*-----------------------------------------------------------------*/
6655 static bool is_LitAOp(asmop *aop)
6656 {
6657   return ((aop->type == AOP_LIT)
6658       || ( (aop->type == AOP_PCODE)
6659           && ( (aop->aopu.pcop->type == PO_LITERAL)
6660               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6661 }
6662
6663
6664
6665 /*-----------------------------------------------------------------*/
6666 /* genCmpEq - generates code for equal to                          */
6667 /*-----------------------------------------------------------------*/
6668 static void genCmpEq (iCode *ic, iCode *ifx)
6669 {
6670   operand *left, *right, *result;
6671   symbol *falselbl = newiTempLabel(NULL);
6672   symbol *donelbl = newiTempLabel(NULL);
6673
6674   int preserve_result = 0;
6675   int generate_result = 0;
6676   int i=0;
6677
6678   FENTRY;
6679   
6680   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6681   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6682   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6683  
6684   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6685
6686   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6687     {
6688       werror(W_POSSBUG2, __FILE__, __LINE__);
6689       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6690       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6691       goto release;
6692     }
6693
6694   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6695     {
6696       operand *tmp = right ;
6697       right = left;
6698       left = tmp;
6699     }
6700
6701   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6702     preserve_result = 1;
6703
6704   if(result && AOP_SIZE(result))
6705     generate_result = 1;
6706
6707   if(generate_result && !preserve_result)
6708     {
6709       for(i = 0; i < AOP_SIZE(result); i++)
6710         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6711     }
6712
6713   for(i=0; i < AOP_SIZE(left); i++)
6714     {
6715       if(AOP_TYPE(left) != AOP_ACC)
6716         {
6717           if(is_LitOp(left))
6718             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6719           else
6720             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6721         }
6722       if(is_LitOp(right))
6723         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6724       else
6725         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6726
6727       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6728     }
6729
6730   // result == true
6731
6732   if(generate_result && preserve_result)
6733     {
6734       for(i = 0; i < AOP_SIZE(result); i++)
6735         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6736     }
6737
6738   if(generate_result)
6739     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6740
6741   if(generate_result && preserve_result)
6742     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6743
6744   if(ifx && IC_TRUE(ifx))
6745     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6746
6747   if(ifx && IC_FALSE(ifx))
6748     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6749
6750   pic16_emitpLabel(falselbl->key);
6751
6752   // result == false
6753
6754   if(ifx && IC_FALSE(ifx))
6755     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6756
6757   if(generate_result && preserve_result)
6758     {
6759       for(i = 0; i < AOP_SIZE(result); i++)
6760         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6761     }
6762
6763   pic16_emitpLabel(donelbl->key);
6764
6765   if(ifx)
6766     ifx->generated = 1;
6767
6768 release:
6769   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6770   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6771   pic16_freeAsmop(result,NULL,ic,TRUE);
6772
6773 }
6774
6775
6776 #if 0
6777 // old version kept for reference
6778
6779 /*-----------------------------------------------------------------*/
6780 /* genCmpEq - generates code for equal to                          */
6781 /*-----------------------------------------------------------------*/
6782 static void genCmpEq (iCode *ic, iCode *ifx)
6783 {
6784     operand *left, *right, *result;
6785     unsigned long lit = 0L;
6786     int size,offset=0;
6787     symbol *falselbl  = newiTempLabel(NULL);
6788
6789
6790     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6791
6792     if(ifx)
6793       DEBUGpic16_emitcode ("; ifx is non-null","");
6794     else
6795       DEBUGpic16_emitcode ("; ifx is null","");
6796
6797     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6798     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6799     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6800
6801     size = max(AOP_SIZE(left),AOP_SIZE(right));
6802
6803     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6804
6805     /* if literal, literal on the right or 
6806     if the right is in a pointer register and left 
6807     is not */
6808     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6809         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6810       operand *tmp = right ;
6811       right = left;
6812       left = tmp;
6813     }
6814
6815
6816     if(ifx && !AOP_SIZE(result)){
6817         symbol *tlbl;
6818         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6819         /* if they are both bit variables */
6820         if (AOP_TYPE(left) == AOP_CRY &&
6821             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6822                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6823             if(AOP_TYPE(right) == AOP_LIT){
6824                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6825                 if(lit == 0L){
6826                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6827                     pic16_emitcode("cpl","c");
6828                 } else if(lit == 1L) {
6829                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6830                 } else {
6831                     pic16_emitcode("clr","c");
6832                 }
6833                 /* AOP_TYPE(right) == AOP_CRY */
6834             } else {
6835                 symbol *lbl = newiTempLabel(NULL);
6836                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6837                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6838                 pic16_emitcode("cpl","c");
6839                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6840             }
6841             /* if true label then we jump if condition
6842             supplied is true */
6843             tlbl = newiTempLabel(NULL);
6844             if ( IC_TRUE(ifx) ) {
6845                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6846                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6847             } else {
6848                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6849                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6850             }
6851             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6852
6853                 {
6854                 /* left and right are both bit variables, result is carry */
6855                         resolvedIfx rIfx;
6856               
6857                         resolveIfx(&rIfx,ifx);
6858
6859                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6860                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6861                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6862                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6863                         genSkipz2(&rIfx,0);
6864                 }
6865         } else {
6866
6867                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6868
6869                         /* They're not both bit variables. Is the right a literal? */
6870                         if(AOP_TYPE(right) == AOP_LIT) {
6871                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6872             
6873                         switch(size) {
6874
6875                                 case 1:
6876                                         switch(lit & 0xff) {
6877                                                 case 1:
6878                                                                 if ( IC_TRUE(ifx) ) {
6879                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6880                                                                         emitSKPNZ;
6881                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6882                                                                 } else {
6883                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6884                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6885                                                                 }
6886                                                                 break;
6887                                                 case 0xff:
6888                                                                 if ( IC_TRUE(ifx) ) {
6889                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6890                                                                         emitSKPNZ;
6891                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6892                                                                 } else {
6893                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6894                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6895                                                                 }
6896                                                                 break;
6897                                                 default:
6898                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6899                                                                 if(lit)
6900                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6901                                                                 genSkip(ifx,'z');
6902                                         } // switch lit
6903
6904
6905                                         /* end of size == 1 */
6906                                         break;
6907               
6908                                 case 2:
6909                                         genc16bit2lit(left,lit,offset);
6910                                         genSkip(ifx,'z');
6911                                         break;
6912                                         /* end of size == 2 */
6913
6914                                 default:
6915                                         /* size is 4 */
6916                                         if(lit==0) {
6917                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6918                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6919                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6920                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6921                                                 genSkip(ifx,'z');
6922                                         } else {
6923                                                 /* search for patterns that can be optimized */
6924
6925                                                 genc16bit2lit(left,lit,0);
6926                                                 lit >>= 16;
6927                                                 if(lit) {
6928                                                                 if(IC_TRUE(ifx))
6929                                                                 emitSKPZ; // if hi word unequal
6930                                                                 else
6931                                                                 emitSKPNZ; // if hi word equal
6932                                                                 // fail early
6933                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6934                                                         genc16bit2lit(left,lit,2);
6935                                                         genSkip(ifx,'z');
6936                                                 } else {
6937                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6938                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6939                                                         genSkip(ifx,'z');
6940                                                 }
6941                                         }
6942                                                 pic16_emitpLabel(falselbl->key);
6943                                                 break;
6944
6945                         } // switch size
6946           
6947                         ifx->generated = 1;
6948                         goto release ;
6949             
6950
6951           } else if(AOP_TYPE(right) == AOP_CRY ) {
6952             /* we know the left is not a bit, but that the right is */
6953             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6954             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6955                       pic16_popGet(AOP(right),offset));
6956             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6957
6958             /* if the two are equal, then W will be 0 and the Z bit is set
6959              * we could test Z now, or go ahead and check the high order bytes if
6960              * the variable we're comparing is larger than a byte. */
6961
6962             while(--size)
6963               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6964
6965             if ( IC_TRUE(ifx) ) {
6966               emitSKPNZ;
6967               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6968               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6969             } else {
6970               emitSKPZ;
6971               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6972               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6973             }
6974
6975           } else {
6976             /* They're both variables that are larger than bits */
6977             int s = size;
6978
6979             tlbl = newiTempLabel(NULL);
6980
6981             while(size--) {
6982               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6983               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6984
6985               if ( IC_TRUE(ifx) ) {
6986                 if(size) {
6987                   emitSKPZ;
6988                 
6989                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6990
6991                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6992                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6993                 } else {
6994                   emitSKPNZ;
6995
6996                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6997
6998
6999                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7000                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7001                 }
7002               } else {
7003                 emitSKPZ;
7004
7005                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7006
7007                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7008                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7009               }
7010               offset++;
7011             }
7012             if(s>1 && IC_TRUE(ifx)) {
7013               pic16_emitpLabel(tlbl->key);
7014               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7015             }
7016           }
7017         }
7018         /* mark the icode as generated */
7019         ifx->generated = 1;
7020         goto release ;
7021     }
7022
7023     /* if they are both bit variables */
7024     if (AOP_TYPE(left) == AOP_CRY &&
7025         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7026         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7027         if(AOP_TYPE(right) == AOP_LIT){
7028             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7029             if(lit == 0L){
7030                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7031                 pic16_emitcode("cpl","c");
7032             } else if(lit == 1L) {
7033                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7034             } else {
7035                 pic16_emitcode("clr","c");
7036             }
7037             /* AOP_TYPE(right) == AOP_CRY */
7038         } else {
7039             symbol *lbl = newiTempLabel(NULL);
7040             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7041             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7042             pic16_emitcode("cpl","c");
7043             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7044         }
7045         /* c = 1 if egal */
7046         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7047             pic16_outBitC(result);
7048             goto release ;
7049         }
7050         if (ifx) {
7051             genIfxJump (ifx,"c");
7052             goto release ;
7053         }
7054         /* if the result is used in an arithmetic operation
7055         then put the result in place */
7056         pic16_outBitC(result);
7057     } else {
7058       
7059       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7060       gencjne(left,right,result,ifx);
7061 /*
7062       if(ifx) 
7063         gencjne(left,right,newiTempLabel(NULL));
7064       else {
7065         if(IC_TRUE(ifx)->key)
7066           gencjne(left,right,IC_TRUE(ifx)->key);
7067         else
7068           gencjne(left,right,IC_FALSE(ifx)->key);
7069         ifx->generated = 1;
7070         goto release ;
7071       }
7072       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7073         pic16_aopPut(AOP(result),"a",0);
7074         goto release ;
7075       }
7076
7077       if (ifx) {
7078         genIfxJump (ifx,"a");
7079         goto release ;
7080       }
7081 */
7082       /* if the result is used in an arithmetic operation
7083          then put the result in place */
7084 /*
7085       if (AOP_TYPE(result) != AOP_CRY) 
7086         pic16_outAcc(result);
7087 */
7088       /* leave the result in acc */
7089     }
7090
7091 release:
7092     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7093     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7094     pic16_freeAsmop(result,NULL,ic,TRUE);
7095 }
7096 #endif
7097
7098 /*-----------------------------------------------------------------*/
7099 /* ifxForOp - returns the icode containing the ifx for operand     */
7100 /*-----------------------------------------------------------------*/
7101 static iCode *ifxForOp ( operand *op, iCode *ic )
7102 {
7103   FENTRY2;
7104
7105     /* if true symbol then needs to be assigned */
7106     if (IS_TRUE_SYMOP(op))
7107         return NULL ;
7108
7109     /* if this has register type condition and
7110     the next instruction is ifx with the same operand
7111     and live to of the operand is upto the ifx only then */
7112     if (ic->next
7113         && ic->next->op == IFX
7114         && IC_COND(ic->next)->key == op->key
7115         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7116         ) {
7117                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7118           return ic->next;
7119     }
7120
7121     /*
7122     if (ic->next &&
7123         ic->next->op == IFX &&
7124         IC_COND(ic->next)->key == op->key) {
7125       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7126       return ic->next;
7127     }
7128     */
7129
7130     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7131     if (ic->next &&
7132         ic->next->op == IFX)
7133       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7134
7135     if (ic->next &&
7136         ic->next->op == IFX &&
7137         IC_COND(ic->next)->key == op->key) {
7138       DEBUGpic16_emitcode ("; "," key is okay");
7139       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7140                            OP_SYMBOL(op)->liveTo,
7141                            ic->next->seq);
7142     }
7143
7144 #if 0
7145     /* the code below is completely untested
7146      * it just allows ulong2fs.c compile -- VR */
7147          
7148     ic = ic->next;
7149     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7150                                         __FILE__, __FUNCTION__, __LINE__);
7151         
7152     /* if this has register type condition and
7153     the next instruction is ifx with the same operand
7154     and live to of the operand is upto the ifx only then */
7155     if (ic->next &&
7156         ic->next->op == IFX &&
7157         IC_COND(ic->next)->key == op->key &&
7158         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7159         return ic->next;
7160
7161     if (ic->next &&
7162         ic->next->op == IFX &&
7163         IC_COND(ic->next)->key == op->key) {
7164       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7165       return ic->next;
7166     }
7167
7168     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7169                                         __FILE__, __FUNCTION__, __LINE__);
7170
7171 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7172 #endif
7173
7174     return NULL;
7175 }
7176 /*-----------------------------------------------------------------*/
7177 /* genAndOp - for && operation                                     */
7178 /*-----------------------------------------------------------------*/
7179 static void genAndOp (iCode *ic)
7180 {
7181   operand *left,*right, *result;
7182 /*     symbol *tlbl; */
7183
7184     FENTRY;
7185
7186     /* note here that && operations that are in an
7187     if statement are taken away by backPatchLabels
7188     only those used in arthmetic operations remain */
7189     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7190     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7191     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7192
7193     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7194
7195     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7196     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7197     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7198
7199     /* if both are bit variables */
7200 /*     if (AOP_TYPE(left) == AOP_CRY && */
7201 /*         AOP_TYPE(right) == AOP_CRY ) { */
7202 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7203 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7204 /*         pic16_outBitC(result); */
7205 /*     } else { */
7206 /*         tlbl = newiTempLabel(NULL); */
7207 /*         pic16_toBoolean(left);     */
7208 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7209 /*         pic16_toBoolean(right); */
7210 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7211 /*         pic16_outBitAcc(result); */
7212 /*     } */
7213
7214     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7215     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7216     pic16_freeAsmop(result,NULL,ic,TRUE);
7217 }
7218
7219
7220 /*-----------------------------------------------------------------*/
7221 /* genOrOp - for || operation                                      */
7222 /*-----------------------------------------------------------------*/
7223 /*
7224   tsd pic port -
7225   modified this code, but it doesn't appear to ever get called
7226 */
7227
7228 static void genOrOp (iCode *ic)
7229 {
7230   operand *left,*right, *result;
7231   symbol *tlbl;
7232
7233     FENTRY;  
7234
7235   /* note here that || operations that are in an
7236     if statement are taken away by backPatchLabels
7237     only those used in arthmetic operations remain */
7238     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7239     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7240     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7241
7242     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7243
7244     /* if both are bit variables */
7245     if (AOP_TYPE(left) == AOP_CRY &&
7246         AOP_TYPE(right) == AOP_CRY ) {
7247       pic16_emitcode("clrc","");
7248       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7249                AOP(left)->aopu.aop_dir,
7250                AOP(left)->aopu.aop_dir);
7251       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7252                AOP(right)->aopu.aop_dir,
7253                AOP(right)->aopu.aop_dir);
7254       pic16_emitcode("setc","");
7255
7256     } else {
7257         tlbl = newiTempLabel(NULL);
7258         pic16_toBoolean(left);
7259         emitSKPZ;
7260         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7261         pic16_toBoolean(right);
7262         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7263
7264         pic16_outBitAcc(result);
7265     }
7266
7267     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7268     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7269     pic16_freeAsmop(result,NULL,ic,TRUE);            
7270 }
7271
7272 /*-----------------------------------------------------------------*/
7273 /* isLiteralBit - test if lit == 2^n                               */
7274 /*-----------------------------------------------------------------*/
7275 static int isLiteralBit(unsigned long lit)
7276 {
7277     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7278     0x100L,0x200L,0x400L,0x800L,
7279     0x1000L,0x2000L,0x4000L,0x8000L,
7280     0x10000L,0x20000L,0x40000L,0x80000L,
7281     0x100000L,0x200000L,0x400000L,0x800000L,
7282     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7283     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7284     int idx;
7285     
7286     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7287     for(idx = 0; idx < 32; idx++)
7288         if(lit == pw[idx])
7289             return idx+1;
7290     return 0;
7291 }
7292
7293 /*-----------------------------------------------------------------*/
7294 /* continueIfTrue -                                                */
7295 /*-----------------------------------------------------------------*/
7296 static void continueIfTrue (iCode *ic)
7297 {
7298   FENTRY;
7299   if(IC_TRUE(ic))
7300     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7301   ic->generated = 1;
7302 }
7303
7304 /*-----------------------------------------------------------------*/
7305 /* jmpIfTrue -                                                     */
7306 /*-----------------------------------------------------------------*/
7307 static void jumpIfTrue (iCode *ic)
7308 {
7309   FENTRY;
7310   if(!IC_TRUE(ic))
7311     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7312   ic->generated = 1;
7313 }
7314
7315 /*-----------------------------------------------------------------*/
7316 /* jmpTrueOrFalse -                                                */
7317 /*-----------------------------------------------------------------*/
7318 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7319 {
7320   // ugly but optimized by peephole
7321   FENTRY;
7322   if(IC_TRUE(ic)){
7323     symbol *nlbl = newiTempLabel(NULL);
7324       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7325       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7326       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7327       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7328   } else {
7329     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7330     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7331   }
7332   ic->generated = 1;
7333 }
7334
7335 /*-----------------------------------------------------------------*/
7336 /* genAnd  - code for and                                          */
7337 /*-----------------------------------------------------------------*/
7338 static void genAnd (iCode *ic, iCode *ifx)
7339 {
7340   operand *left, *right, *result;
7341   int size, offset=0;  
7342   unsigned long lit = 0L;
7343   int bytelit = 0;
7344   resolvedIfx rIfx;
7345
7346     FENTRY;
7347     
7348   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7349   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7350   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7351
7352   resolveIfx(&rIfx,ifx);
7353
7354   /* if left is a literal & right is not then exchange them */
7355   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7356       AOP_NEEDSACC(left)) {
7357     operand *tmp = right ;
7358     right = left;
7359     left = tmp;
7360   }
7361
7362   /* if result = right then exchange them */
7363   if(pic16_sameRegs(AOP(result),AOP(right))){
7364     operand *tmp = right ;
7365     right = left;
7366     left = tmp;
7367   }
7368
7369   /* if right is bit then exchange them */
7370   if (AOP_TYPE(right) == AOP_CRY &&
7371       AOP_TYPE(left) != AOP_CRY){
7372     operand *tmp = right ;
7373     right = left;
7374     left = tmp;
7375   }
7376   if(AOP_TYPE(right) == AOP_LIT)
7377     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7378
7379   size = AOP_SIZE(result);
7380
7381   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7382
7383   // if(bit & yy)
7384   // result = bit & yy;
7385   if (AOP_TYPE(left) == AOP_CRY){
7386     // c = bit & literal;
7387     if(AOP_TYPE(right) == AOP_LIT){
7388       if(lit & 1) {
7389         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7390           // no change
7391           goto release;
7392         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7393       } else {
7394         // bit(result) = 0;
7395         if(size && (AOP_TYPE(result) == AOP_CRY)){
7396           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7397           goto release;
7398         }
7399         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7400           jumpIfTrue(ifx);
7401           goto release;
7402         }
7403         pic16_emitcode("clr","c");
7404       }
7405     } else {
7406       if (AOP_TYPE(right) == AOP_CRY){
7407         // c = bit & bit;
7408         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7409         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7410       } else {
7411         // c = bit & val;
7412         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7413         // c = lsb
7414         pic16_emitcode("rrc","a");
7415         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7416       }
7417     }
7418     // bit = c
7419     // val = c
7420     if(size)
7421       pic16_outBitC(result);
7422     // if(bit & ...)
7423     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7424       genIfxJump(ifx, "c");           
7425     goto release ;
7426   }
7427
7428   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7429   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7430   if((AOP_TYPE(right) == AOP_LIT) &&
7431      (AOP_TYPE(result) == AOP_CRY) &&
7432      (AOP_TYPE(left) != AOP_CRY)){
7433     int posbit = isLiteralBit(lit);
7434     /* left &  2^n */
7435     if(posbit){
7436       posbit--;
7437       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7438       // bit = left & 2^n
7439       if(size)
7440         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7441       // if(left &  2^n)
7442       else{
7443         if(ifx){
7444 /*
7445           if(IC_TRUE(ifx)) {
7446             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7447             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7448           } else {
7449             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7450             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7451           }
7452 */
7453         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7454         size = AOP_SIZE(left);
7455
7456         {
7457           int bp = posbit, ofs=0;
7458           
7459             while(bp > 7) {
7460               bp -= 8;
7461               ofs++;
7462             }
7463         
7464           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7465                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7466
7467         }
7468 /*
7469           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7470                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7471 */
7472           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7473           
7474           ifx->generated = 1;
7475         }
7476         goto release;
7477       }
7478     } else {
7479       symbol *tlbl = newiTempLabel(NULL);
7480       int sizel = AOP_SIZE(left);
7481
7482       if(size)
7483         emitSETC;
7484
7485       while(sizel--) {
7486         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7487
7488           /* patch provided by Aaron Colwell */
7489           if((posbit = isLiteralBit(bytelit)) != 0) {
7490               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7491                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7492                                                 (posbit-1),0, PO_GPR_REGISTER));
7493
7494               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7495 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7496           } else {
7497               if (bytelit == 0xff) {
7498                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7499                    * a peephole could optimize it out -- VR */
7500                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7501               } else {
7502                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7503                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7504               }
7505
7506               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7507                             pic16_popGetLabel(tlbl->key));
7508           }
7509         
7510 #if 0
7511           /* old code, left here for reference -- VR 09/2004 */
7512           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7513           // byte ==  2^n ?
7514           if((posbit = isLiteralBit(bytelit)) != 0)
7515             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7516           else{
7517             if(bytelit != 0x0FFL)
7518               pic16_emitcode("anl","a,%s",
7519                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7520             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7521           }
7522 #endif
7523         }
7524         offset++;
7525       }
7526       // bit = left & literal
7527       if(size) {
7528         emitCLRC;
7529         pic16_emitpLabel(tlbl->key);
7530       }
7531       // if(left & literal)
7532       else {
7533         if(ifx) {
7534           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7535           ifx->generated = 1;
7536         }
7537         pic16_emitpLabel(tlbl->key);
7538         goto release;
7539       }
7540     }
7541
7542     pic16_outBitC(result);
7543     goto release ;
7544   }
7545
7546   /* if left is same as result */
7547   if(pic16_sameRegs(AOP(result),AOP(left))){
7548     int know_W = -1;
7549     for(;size--; offset++,lit>>=8) {
7550       if(AOP_TYPE(right) == AOP_LIT){
7551         switch(lit & 0xff) {
7552         case 0x00:
7553           /*  and'ing with 0 has clears the result */
7554 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7555           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7556           break;
7557         case 0xff:
7558           /* and'ing with 0xff is a nop when the result and left are the same */
7559           break;
7560
7561         default:
7562           {
7563             int p = pic16_my_powof2( (~lit) & 0xff );
7564             if(p>=0) {
7565               /* only one bit is set in the literal, so use a bcf instruction */
7566 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7567               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7568
7569             } else {
7570               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7571               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7572               if(know_W != (lit&0xff))
7573                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7574               know_W = lit &0xff;
7575               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7576             }
7577           }    
7578         }
7579       } else {
7580         if (AOP_TYPE(left) == AOP_ACC) {
7581           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7582         } else {                    
7583           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7584           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7585
7586         }
7587       }
7588     }
7589
7590   } else {
7591     // left & result in different registers
7592     if(AOP_TYPE(result) == AOP_CRY){
7593       // result = bit
7594       // if(size), result in bit
7595       // if(!size && ifx), conditional oper: if(left & right)
7596       symbol *tlbl = newiTempLabel(NULL);
7597       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7598       if(size)
7599         pic16_emitcode("setb","c");
7600       while(sizer--){
7601         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7602         pic16_emitcode("anl","a,%s",
7603                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7604         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7605         offset++;
7606       }
7607       if(size){
7608         CLRC;
7609         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7610         pic16_outBitC(result);
7611       } else if(ifx)
7612         jmpTrueOrFalse(ifx, tlbl);
7613     } else {
7614       for(;(size--);offset++) {
7615         // normal case
7616         // result = left & right
7617         if(AOP_TYPE(right) == AOP_LIT){
7618           int t = (lit >> (offset*8)) & 0x0FFL;
7619           switch(t) { 
7620           case 0x00:
7621             pic16_emitcode("clrf","%s",
7622                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7623             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7624             break;
7625           case 0xff:
7626             pic16_emitcode("movf","%s,w",
7627                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7628             pic16_emitcode("movwf","%s",
7629                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7630             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7631             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7632             break;
7633           default:
7634             pic16_emitcode("movlw","0x%x",t);
7635             pic16_emitcode("andwf","%s,w",
7636                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7637             pic16_emitcode("movwf","%s",
7638                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7639               
7640             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7641             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7642             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7643           }
7644           continue;
7645         }
7646
7647         if (AOP_TYPE(left) == AOP_ACC) {
7648           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7649           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7650         } else {
7651           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7652           pic16_emitcode("andwf","%s,w",
7653                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7655           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7656         }
7657         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7658         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7659       }
7660     }
7661   }
7662
7663   release :
7664     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7665   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7666   pic16_freeAsmop(result,NULL,ic,TRUE);     
7667 }
7668
7669 /*-----------------------------------------------------------------*/
7670 /* genOr  - code for or                                            */
7671 /*-----------------------------------------------------------------*/
7672 static void genOr (iCode *ic, iCode *ifx)
7673 {
7674     operand *left, *right, *result;
7675     int size, offset=0;
7676     unsigned long lit = 0L;
7677
7678     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7679
7680     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7681     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7682     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7683
7684     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7685
7686     /* if left is a literal & right is not then exchange them */
7687     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7688         AOP_NEEDSACC(left)) {
7689         operand *tmp = right ;
7690         right = left;
7691         left = tmp;
7692     }
7693
7694     /* if result = right then exchange them */
7695     if(pic16_sameRegs(AOP(result),AOP(right))){
7696         operand *tmp = right ;
7697         right = left;
7698         left = tmp;
7699     }
7700
7701     /* if right is bit then exchange them */
7702     if (AOP_TYPE(right) == AOP_CRY &&
7703         AOP_TYPE(left) != AOP_CRY){
7704         operand *tmp = right ;
7705         right = left;
7706         left = tmp;
7707     }
7708
7709     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7710
7711     if(AOP_TYPE(right) == AOP_LIT)
7712         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7713
7714     size = AOP_SIZE(result);
7715
7716     // if(bit | yy)
7717     // xx = bit | yy;
7718     if (AOP_TYPE(left) == AOP_CRY){
7719         if(AOP_TYPE(right) == AOP_LIT){
7720             // c = bit & literal;
7721             if(lit){
7722                 // lit != 0 => result = 1
7723                 if(AOP_TYPE(result) == AOP_CRY){
7724                   if(size)
7725                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7726                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7727                   //     AOP(result)->aopu.aop_dir,
7728                   //     AOP(result)->aopu.aop_dir);
7729                     else if(ifx)
7730                         continueIfTrue(ifx);
7731                     goto release;
7732                 }
7733             } else {
7734                 // lit == 0 => result = left
7735                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7736                     goto release;
7737                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7738             }
7739         } else {
7740             if (AOP_TYPE(right) == AOP_CRY){
7741               if(pic16_sameRegs(AOP(result),AOP(left))){
7742                 // c = bit | bit;
7743                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7744                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7745                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7746
7747                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7748                          AOP(result)->aopu.aop_dir,
7749                          AOP(result)->aopu.aop_dir);
7750                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7751                          AOP(right)->aopu.aop_dir,
7752                          AOP(right)->aopu.aop_dir);
7753                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7754                          AOP(result)->aopu.aop_dir,
7755                          AOP(result)->aopu.aop_dir);
7756               } else {
7757                 if( AOP_TYPE(result) == AOP_ACC) {
7758                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7759                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7760                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7761                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7762
7763                 } else {
7764
7765                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7766                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7767                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7768                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7769
7770                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7771                                  AOP(result)->aopu.aop_dir,
7772                                  AOP(result)->aopu.aop_dir);
7773                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7774                                  AOP(right)->aopu.aop_dir,
7775                                  AOP(right)->aopu.aop_dir);
7776                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7777                                  AOP(left)->aopu.aop_dir,
7778                                  AOP(left)->aopu.aop_dir);
7779                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7780                                  AOP(result)->aopu.aop_dir,
7781                                  AOP(result)->aopu.aop_dir);
7782                 }
7783               }
7784             } else {
7785                 // c = bit | val;
7786                 symbol *tlbl = newiTempLabel(NULL);
7787                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7788
7789
7790                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7791                 if( AOP_TYPE(right) == AOP_ACC) {
7792                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7793                   emitSKPNZ;
7794                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7795                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7796                 }
7797
7798
7799
7800                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7801                     pic16_emitcode(";XXX setb","c");
7802                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7803                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7804                 pic16_toBoolean(right);
7805                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7806                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7807                     jmpTrueOrFalse(ifx, tlbl);
7808                     goto release;
7809                 } else {
7810                     CLRC;
7811                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7812                 }
7813             }
7814         }
7815         // bit = c
7816         // val = c
7817         if(size)
7818             pic16_outBitC(result);
7819         // if(bit | ...)
7820         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7821             genIfxJump(ifx, "c");           
7822         goto release ;
7823     }
7824
7825     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7826     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7827     if((AOP_TYPE(right) == AOP_LIT) &&
7828        (AOP_TYPE(result) == AOP_CRY) &&
7829        (AOP_TYPE(left) != AOP_CRY)){
7830         if(lit){
7831           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7832             // result = 1
7833             if(size)
7834                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7835             else 
7836                 continueIfTrue(ifx);
7837             goto release;
7838         } else {
7839           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7840             // lit = 0, result = boolean(left)
7841             if(size)
7842                 pic16_emitcode(";XXX setb","c");
7843             pic16_toBoolean(right);
7844             if(size){
7845                 symbol *tlbl = newiTempLabel(NULL);
7846                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7847                 CLRC;
7848                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7849             } else {
7850                 genIfxJump (ifx,"a");
7851                 goto release;
7852             }
7853         }
7854         pic16_outBitC(result);
7855         goto release ;
7856     }
7857
7858     /* if left is same as result */
7859     if(pic16_sameRegs(AOP(result),AOP(left))){
7860       int know_W = -1;
7861       for(;size--; offset++,lit>>=8) {
7862         if(AOP_TYPE(right) == AOP_LIT){
7863           if((lit & 0xff) == 0)
7864             /*  or'ing with 0 has no effect */
7865             continue;
7866           else {
7867             int p = pic16_my_powof2(lit & 0xff);
7868             if(p>=0) {
7869               /* only one bit is set in the literal, so use a bsf instruction */
7870               pic16_emitpcode(POC_BSF,
7871                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7872             } else {
7873               if(know_W != (lit & 0xff))
7874                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7875               know_W = lit & 0xff;
7876               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7877             }
7878                     
7879           }
7880         } else {
7881           if (AOP_TYPE(left) == AOP_ACC) {
7882             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7883             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7884           } else {                  
7885             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7886             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7887
7888             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7889             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890
7891           }
7892         }
7893       }
7894     } else {
7895         // left & result in different registers
7896         if(AOP_TYPE(result) == AOP_CRY){
7897             // result = bit
7898             // if(size), result in bit
7899             // if(!size && ifx), conditional oper: if(left | right)
7900             symbol *tlbl = newiTempLabel(NULL);
7901             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7902             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7903
7904
7905             if(size)
7906                 pic16_emitcode(";XXX setb","c");
7907             while(sizer--){
7908                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7909                 pic16_emitcode(";XXX orl","a,%s",
7910                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7911                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7912                 offset++;
7913             }
7914             if(size){
7915                 CLRC;
7916                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7917                 pic16_outBitC(result);
7918             } else if(ifx)
7919                 jmpTrueOrFalse(ifx, tlbl);
7920         } else for(;(size--);offset++){
7921           // normal case
7922           // result = left & right
7923           if(AOP_TYPE(right) == AOP_LIT){
7924             int t = (lit >> (offset*8)) & 0x0FFL;
7925             switch(t) { 
7926             case 0x00:
7927               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7928               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7929
7930               pic16_emitcode("movf","%s,w",
7931                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7932               pic16_emitcode("movwf","%s",
7933                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7934               break;
7935             default:
7936               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7937               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7938               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7939
7940               pic16_emitcode("movlw","0x%x",t);
7941               pic16_emitcode("iorwf","%s,w",
7942                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7943               pic16_emitcode("movwf","%s",
7944                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7945               
7946             }
7947             continue;
7948           }
7949
7950           // faster than result <- left, anl result,right
7951           // and better if result is SFR
7952           if (AOP_TYPE(left) == AOP_ACC) {
7953             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7954             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7955           } else {
7956             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7957             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7958
7959             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7960             pic16_emitcode("iorwf","%s,w",
7961                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7962           }
7963           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7964           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7965         }
7966     }
7967
7968 release :
7969     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7970     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7971     pic16_freeAsmop(result,NULL,ic,TRUE);     
7972 }
7973
7974 /*-----------------------------------------------------------------*/
7975 /* genXor - code for xclusive or                                   */
7976 /*-----------------------------------------------------------------*/
7977 static void genXor (iCode *ic, iCode *ifx)
7978 {
7979   operand *left, *right, *result;
7980   int size, offset=0;
7981   unsigned long lit = 0L;
7982
7983   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7984
7985   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7986   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7987   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7988
7989   /* if left is a literal & right is not ||
7990      if left needs acc & right does not */
7991   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7992       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7993     operand *tmp = right ;
7994     right = left;
7995     left = tmp;
7996   }
7997
7998   /* if result = right then exchange them */
7999   if(pic16_sameRegs(AOP(result),AOP(right))){
8000     operand *tmp = right ;
8001     right = left;
8002     left = tmp;
8003   }
8004
8005   /* if right is bit then exchange them */
8006   if (AOP_TYPE(right) == AOP_CRY &&
8007       AOP_TYPE(left) != AOP_CRY){
8008     operand *tmp = right ;
8009     right = left;
8010     left = tmp;
8011   }
8012   if(AOP_TYPE(right) == AOP_LIT)
8013     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8014
8015   size = AOP_SIZE(result);
8016
8017   // if(bit ^ yy)
8018   // xx = bit ^ yy;
8019   if (AOP_TYPE(left) == AOP_CRY){
8020     if(AOP_TYPE(right) == AOP_LIT){
8021       // c = bit & literal;
8022       if(lit>>1){
8023         // lit>>1  != 0 => result = 1
8024         if(AOP_TYPE(result) == AOP_CRY){
8025           if(size)
8026             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8027             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8028           else if(ifx)
8029             continueIfTrue(ifx);
8030           goto release;
8031         }
8032         pic16_emitcode("setb","c");
8033       } else{
8034         // lit == (0 or 1)
8035         if(lit == 0){
8036           // lit == 0, result = left
8037           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8038             goto release;
8039           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8040         } else{
8041           // lit == 1, result = not(left)
8042           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8043             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8044             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8045             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8046             goto release;
8047           } else {
8048             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8049             pic16_emitcode("cpl","c");
8050           }
8051         }
8052       }
8053
8054     } else {
8055       // right != literal
8056       symbol *tlbl = newiTempLabel(NULL);
8057       if (AOP_TYPE(right) == AOP_CRY){
8058         // c = bit ^ bit;
8059         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8060       }
8061       else{
8062         int sizer = AOP_SIZE(right);
8063         // c = bit ^ val
8064         // if val>>1 != 0, result = 1
8065         pic16_emitcode("setb","c");
8066         while(sizer){
8067           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8068           if(sizer == 1)
8069             // test the msb of the lsb
8070             pic16_emitcode("anl","a,#0xfe");
8071           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8072           sizer--;
8073         }
8074         // val = (0,1)
8075         pic16_emitcode("rrc","a");
8076       }
8077       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8078       pic16_emitcode("cpl","c");
8079       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8080     }
8081     // bit = c
8082     // val = c
8083     if(size)
8084       pic16_outBitC(result);
8085     // if(bit | ...)
8086     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8087       genIfxJump(ifx, "c");           
8088     goto release ;
8089   }
8090
8091   if(pic16_sameRegs(AOP(result),AOP(left))){
8092     /* if left is same as result */
8093     for(;size--; offset++) {
8094       if(AOP_TYPE(right) == AOP_LIT){
8095         int t  = (lit >> (offset*8)) & 0x0FFL;
8096         if(t == 0x00L)
8097           continue;
8098         else
8099           if (IS_AOP_PREG(left)) {
8100             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8101             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8102             pic16_aopPut(AOP(result),"a",offset);
8103           } else {
8104             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8105             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8106             pic16_emitcode("xrl","%s,%s",
8107                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8108                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8109           }
8110       } else {
8111         if (AOP_TYPE(left) == AOP_ACC)
8112           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8113         else {
8114           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8115           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8116 /*
8117           if (IS_AOP_PREG(left)) {
8118             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119             pic16_aopPut(AOP(result),"a",offset);
8120           } else
8121             pic16_emitcode("xrl","%s,a",
8122                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8123 */
8124         }
8125       }
8126     }
8127   } else {
8128     // left & result in different registers
8129     if(AOP_TYPE(result) == AOP_CRY){
8130       // result = bit
8131       // if(size), result in bit
8132       // if(!size && ifx), conditional oper: if(left ^ right)
8133       symbol *tlbl = newiTempLabel(NULL);
8134       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8135       if(size)
8136         pic16_emitcode("setb","c");
8137       while(sizer--){
8138         if((AOP_TYPE(right) == AOP_LIT) &&
8139            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8140           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8141         } else {
8142           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8143           pic16_emitcode("xrl","a,%s",
8144                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8145         }
8146         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8147         offset++;
8148       }
8149       if(size){
8150         CLRC;
8151         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8152         pic16_outBitC(result);
8153       } else if(ifx)
8154         jmpTrueOrFalse(ifx, tlbl);
8155     } else for(;(size--);offset++){
8156       // normal case
8157       // result = left & right
8158       if(AOP_TYPE(right) == AOP_LIT){
8159         int t = (lit >> (offset*8)) & 0x0FFL;
8160         switch(t) { 
8161         case 0x00:
8162           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8163           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8164           pic16_emitcode("movf","%s,w",
8165                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8166           pic16_emitcode("movwf","%s",
8167                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8168           break;
8169         case 0xff:
8170           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8171           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8172           pic16_emitcode("comf","%s,w",
8173                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174           pic16_emitcode("movwf","%s",
8175                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8176           break;
8177         default:
8178           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8179           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8180           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181           pic16_emitcode("movlw","0x%x",t);
8182           pic16_emitcode("xorwf","%s,w",
8183                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8184           pic16_emitcode("movwf","%s",
8185                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8186
8187         }
8188         continue;
8189       }
8190
8191       // faster than result <- left, anl result,right
8192       // and better if result is SFR
8193       if (AOP_TYPE(left) == AOP_ACC) {
8194         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8195         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8196       } else {
8197         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8198         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8199         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8200         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8201       }
8202       if ( AOP_TYPE(result) != AOP_ACC){
8203         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8204         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8205       }
8206     }
8207   }
8208
8209   release :
8210     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8211   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8212   pic16_freeAsmop(result,NULL,ic,TRUE);     
8213 }
8214
8215 /*-----------------------------------------------------------------*/
8216 /* genInline - write the inline code out                           */
8217 /*-----------------------------------------------------------------*/
8218 static void genInline (iCode *ic)
8219 {
8220   char *buffer, *bp, *bp1;
8221     
8222         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8223
8224         _G.inLine += (!options.asmpeep);
8225
8226         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8227         strcpy(buffer,IC_INLINE(ic));
8228
8229 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8230
8231         /* emit each line as a code */
8232         while (*bp) {
8233                 if (*bp == '\n') {
8234                         *bp++ = '\0';
8235
8236                         if(*bp1)
8237                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8238                         bp1 = bp;
8239                 } else {
8240                         if (*bp == ':') {
8241                                 bp++;
8242                                 *bp = '\0';
8243                                 bp++;
8244
8245                                 /* print label, use this special format with NULL directive
8246                                  * to denote that the argument should not be indented with tab */
8247                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8248                                 bp1 = bp;
8249                         } else
8250                                 bp++;
8251                 }
8252         }
8253
8254         if ((bp1 != bp) && *bp1)
8255                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8256
8257
8258     Safe_free(buffer);
8259
8260     _G.inLine -= (!options.asmpeep);
8261 }
8262
8263 /*-----------------------------------------------------------------*/
8264 /* genRRC - rotate right with carry                                */
8265 /*-----------------------------------------------------------------*/
8266 static void genRRC (iCode *ic)
8267 {
8268   operand *left , *result ;
8269   int size, offset = 0, same;
8270
8271   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8272
8273   /* rotate right with carry */
8274   left = IC_LEFT(ic);
8275   result=IC_RESULT(ic);
8276   pic16_aopOp (left,ic,FALSE);
8277   pic16_aopOp (result,ic,FALSE);
8278
8279   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8280
8281   same = pic16_sameRegs(AOP(result),AOP(left));
8282
8283   size = AOP_SIZE(result);    
8284
8285   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8286
8287   /* get the lsb and put it into the carry */
8288   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8289
8290   offset = 0 ;
8291
8292   while(size--) {
8293
8294     if(same) {
8295       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8296     } else {
8297       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8298       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8299     }
8300
8301     offset++;
8302   }
8303
8304   pic16_freeAsmop(left,NULL,ic,TRUE);
8305   pic16_freeAsmop(result,NULL,ic,TRUE);
8306 }
8307
8308 /*-----------------------------------------------------------------*/
8309 /* genRLC - generate code for rotate left with carry               */
8310 /*-----------------------------------------------------------------*/
8311 static void genRLC (iCode *ic)
8312 {    
8313   operand *left , *result ;
8314   int size, offset = 0;
8315   int same;
8316
8317   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8318   /* rotate right with carry */
8319   left = IC_LEFT(ic);
8320   result=IC_RESULT(ic);
8321   pic16_aopOp (left,ic,FALSE);
8322   pic16_aopOp (result,ic,FALSE);
8323
8324   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8325
8326   same = pic16_sameRegs(AOP(result),AOP(left));
8327
8328   /* move it to the result */
8329   size = AOP_SIZE(result);    
8330
8331   /* get the msb and put it into the carry */
8332   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8333
8334   offset = 0 ;
8335
8336   while(size--) {
8337
8338     if(same) {
8339       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8340     } else {
8341       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8342       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8343     }
8344
8345     offset++;
8346   }
8347
8348
8349   pic16_freeAsmop(left,NULL,ic,TRUE);
8350   pic16_freeAsmop(result,NULL,ic,TRUE);
8351 }
8352
8353
8354 /* gpasm can get the highest order bit with HIGH/UPPER
8355  * so the following probably is not needed -- VR */
8356  
8357 /*-----------------------------------------------------------------*/
8358 /* genGetHbit - generates code get highest order bit               */
8359 /*-----------------------------------------------------------------*/
8360 static void genGetHbit (iCode *ic)
8361 {
8362     operand *left, *result;
8363     left = IC_LEFT(ic);
8364     result=IC_RESULT(ic);
8365     pic16_aopOp (left,ic,FALSE);
8366     pic16_aopOp (result,ic,FALSE);
8367
8368     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8369     /* get the highest order byte into a */
8370     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8371     if(AOP_TYPE(result) == AOP_CRY){
8372         pic16_emitcode("rlc","a");
8373         pic16_outBitC(result);
8374     }
8375     else{
8376         pic16_emitcode("rl","a");
8377         pic16_emitcode("anl","a,#0x01");
8378         pic16_outAcc(result);
8379     }
8380
8381
8382     pic16_freeAsmop(left,NULL,ic,TRUE);
8383     pic16_freeAsmop(result,NULL,ic,TRUE);
8384 }
8385
8386 #if 0
8387 /*-----------------------------------------------------------------*/
8388 /* AccRol - rotate left accumulator by known count                 */
8389 /*-----------------------------------------------------------------*/
8390 static void AccRol (int shCount)
8391 {
8392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8393     shCount &= 0x0007;              // shCount : 0..7
8394     switch(shCount){
8395         case 0 :
8396             break;
8397         case 1 :
8398             pic16_emitcode("rl","a");
8399             break;
8400         case 2 :
8401             pic16_emitcode("rl","a");
8402             pic16_emitcode("rl","a");
8403             break;
8404         case 3 :
8405             pic16_emitcode("swap","a");
8406             pic16_emitcode("rr","a");
8407             break;
8408         case 4 :
8409             pic16_emitcode("swap","a");
8410             break;
8411         case 5 :
8412             pic16_emitcode("swap","a");
8413             pic16_emitcode("rl","a");
8414             break;
8415         case 6 :
8416             pic16_emitcode("rr","a");
8417             pic16_emitcode("rr","a");
8418             break;
8419         case 7 :
8420             pic16_emitcode("rr","a");
8421             break;
8422     }
8423 }
8424 #endif
8425
8426 /*-----------------------------------------------------------------*/
8427 /* AccLsh - left shift accumulator by known count                  */
8428 /*-----------------------------------------------------------------*/
8429 static void AccLsh (int shCount)
8430 {
8431         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8432         switch(shCount){
8433                 case 0 :
8434                         return;
8435                         break;
8436                 case 1 :
8437                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8438                         break;
8439                 case 2 :
8440                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8441                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8442                         break;
8443                 case 3 :
8444                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8445                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8446                         break;
8447                 case 4 :
8448                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         break;
8450                 case 5 :
8451                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8452                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8453                         break;
8454                 case 6 :
8455                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8456                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8457                         break;
8458                 case 7 :
8459                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460                         break;
8461         }
8462
8463         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8464 }
8465
8466 /*-----------------------------------------------------------------*/
8467 /* AccRsh - right shift accumulator by known count                 */
8468 /*-----------------------------------------------------------------*/
8469 static void AccRsh (int shCount, int andmask)
8470 {
8471         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8472         switch(shCount){
8473                 case 0 :
8474                         return; break;
8475                 case 1 :
8476                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8477                         break;
8478                 case 2 :
8479                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8480                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8481                         break;
8482                 case 3 :
8483                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8484                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8485                         break;
8486                 case 4 :
8487                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8488                         break;
8489                 case 5 :
8490                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8491                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8492                         break;
8493                 case 6 :
8494                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8495                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8496                         break;
8497                 case 7 :
8498                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8499                         break;
8500         }
8501         
8502         if(andmask)
8503                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8504         else
8505                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8506 }
8507
8508 #if 0
8509 /*-----------------------------------------------------------------*/
8510 /* AccSRsh - signed right shift accumulator by known count                 */
8511 /*-----------------------------------------------------------------*/
8512 static void AccSRsh (int shCount)
8513 {
8514     symbol *tlbl ;
8515     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8516     if(shCount != 0){
8517         if(shCount == 1){
8518             pic16_emitcode("mov","c,acc.7");
8519             pic16_emitcode("rrc","a");
8520         } else if(shCount == 2){
8521             pic16_emitcode("mov","c,acc.7");
8522             pic16_emitcode("rrc","a");
8523             pic16_emitcode("mov","c,acc.7");
8524             pic16_emitcode("rrc","a");
8525         } else {
8526             tlbl = newiTempLabel(NULL);
8527             /* rotate right accumulator */
8528             AccRol(8 - shCount);
8529             /* and kill the higher order bits */
8530             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8531             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8532             pic16_emitcode("orl","a,#0x%02x",
8533                      (unsigned char)~SRMask[shCount]);
8534             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8535         }
8536     }
8537 }
8538 #endif
8539
8540 /*-----------------------------------------------------------------*/
8541 /* shiftR1Left2Result - shift right one byte from left to result   */
8542 /*-----------------------------------------------------------------*/
8543 static void shiftR1Left2ResultSigned (operand *left, int offl,
8544                                 operand *result, int offr,
8545                                 int shCount)
8546 {
8547   int same;
8548
8549   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8550
8551   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8552
8553   switch(shCount) {
8554   case 1:
8555     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8556     if(same) 
8557       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8558     else {
8559       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8560       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8561     }
8562
8563     break;
8564   case 2:
8565
8566     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8567     if(same) 
8568       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8569     else {
8570       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8571       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8572     }
8573     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8574     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8575
8576     break;
8577
8578   case 3:
8579     if(same)
8580       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8581     else {
8582       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8583       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8584     }
8585
8586     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8587     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8588     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8589
8590     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8591     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8592
8593     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8594     break;
8595
8596   case 4:
8597     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8598     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8599     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8600     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8601     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8602     break;
8603   case 5:
8604     if(same) {
8605       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8606     } else {
8607       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8608       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8609     }
8610     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8611     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8612     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8613     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8614     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8615     break;
8616
8617   case 6:
8618     if(same) {
8619       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8620       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8621       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8622       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8623       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8624       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8625     } else {
8626       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8627       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8628       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8629       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8630       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8631     }
8632     break;
8633
8634   case 7:
8635     if(same) {
8636       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8637       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8638       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8639       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8640     } else {
8641       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8642       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8643       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8644     }
8645
8646   default:
8647     break;
8648   }
8649 }
8650
8651 /*-----------------------------------------------------------------*/
8652 /* shiftR1Left2Result - shift right one byte from left to result   */
8653 /*-----------------------------------------------------------------*/
8654 static void shiftR1Left2Result (operand *left, int offl,
8655                                 operand *result, int offr,
8656                                 int shCount, int sign)
8657 {
8658   int same;
8659
8660   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8661
8662   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8663
8664   /* Copy the msb into the carry if signed. */
8665   if(sign) {
8666     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8667     return;
8668   }
8669
8670
8671
8672   switch(shCount) {
8673   case 1:
8674     emitCLRC;
8675     if(same) 
8676       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8677     else {
8678       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8679       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8680     }
8681     break;
8682   case 2:
8683     emitCLRC;
8684     if(same) {
8685       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8686     } else {
8687       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8688       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689     }
8690     emitCLRC;
8691     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8692
8693     break;
8694   case 3:
8695     if(same)
8696       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8697     else {
8698       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8699       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8700     }
8701
8702     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8703     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8704     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8705     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8706     break;
8707       
8708   case 4:
8709     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8710     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8711     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712     break;
8713
8714   case 5:
8715     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8716     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8717     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8718     //emitCLRC;
8719     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8720
8721     break;
8722   case 6:
8723
8724     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8725     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8726     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8727     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8728     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8729     break;
8730
8731   case 7:
8732
8733     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8734     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8735     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8736
8737     break;
8738
8739   default:
8740     break;
8741   }
8742 }
8743
8744 /*-----------------------------------------------------------------*/
8745 /* shiftL1Left2Result - shift left one byte from left to result    */
8746 /*-----------------------------------------------------------------*/
8747 static void shiftL1Left2Result (operand *left, int offl,
8748                                 operand *result, int offr, int shCount)
8749 {
8750   int same;
8751
8752   //    char *l;
8753   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8754
8755   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8756   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8757     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8758     //    MOVA(l);
8759     /* shift left accumulator */
8760     //AccLsh(shCount); // don't comment out just yet...
8761   //    pic16_aopPut(AOP(result),"a",offr);
8762
8763   switch(shCount) {
8764   case 1:
8765     /* Shift left 1 bit position */
8766     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8767     if(same) {
8768       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8769     } else {
8770       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8771       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772     }
8773     break;
8774   case 2:
8775     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8776     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8777     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8778     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8779     break;
8780   case 3:
8781     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8783     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8785     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8786     break;
8787   case 4:
8788     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8790     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8791     break;
8792   case 5:
8793     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8794     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8795     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8796     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8797     break;
8798   case 6:
8799     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8800     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8801     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8802     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8803     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8804     break;
8805   case 7:
8806     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8807     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8808     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8809     break;
8810
8811   default:
8812     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8813   }
8814
8815 }
8816
8817 /*-----------------------------------------------------------------*/
8818 /* movLeft2Result - move byte from left to result                  */
8819 /*-----------------------------------------------------------------*/
8820 static void movLeft2Result (operand *left, int offl,
8821                             operand *result, int offr)
8822 {
8823   char *l;
8824   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8826     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8827
8828     if (*l == '@' && (IS_AOP_PREG(result))) {
8829       pic16_emitcode("mov","a,%s",l);
8830       pic16_aopPut(AOP(result),"a",offr);
8831     } else {
8832       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8833       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8834     }
8835   }
8836 }
8837
8838 /*-----------------------------------------------------------------*/
8839 /* shiftL2Left2Result - shift left two bytes from left to result   */
8840 /*-----------------------------------------------------------------*/
8841 static void shiftL2Left2Result (operand *left, int offl,
8842                                 operand *result, int offr, int shCount)
8843 {
8844   int same = pic16_sameRegs(AOP(result), AOP(left));
8845   int i;
8846
8847   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8848
8849   if (same && (offl != offr)) { // shift bytes
8850     if (offr > offl) {
8851        for(i=1;i>-1;i--) {
8852          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8853          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8854        }
8855     } else { // just treat as different later on
8856                 same = 0;
8857     }
8858   }
8859
8860   if(same) {
8861     switch(shCount) {
8862     case 0:
8863       break;
8864     case 1:
8865     case 2:
8866     case 3:
8867
8868       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8869       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8871
8872       while(--shCount) {
8873                 emitCLRC;
8874                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8875                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8876       }
8877
8878       break;
8879     case 4:
8880     case 5:
8881       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8882       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8883       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8884       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8885       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8886       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8887       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8888       if(shCount >=5) {
8889                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8890                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8891       }
8892       break;
8893     case 6:
8894       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8895       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8896       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8897       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8898       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8899       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8900       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8901       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8902       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8903       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8904       break;
8905     case 7:
8906       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8907       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8909       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8910       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8911     }
8912
8913   } else {
8914     switch(shCount) {
8915     case 0:
8916       break;
8917     case 1:
8918     case 2:
8919     case 3:
8920       /* note, use a mov/add for the shift since the mov has a
8921          chance of getting optimized out */
8922       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8923       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8924       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8925       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8926       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8927
8928       while(--shCount) {
8929                 emitCLRC;
8930                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8931                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8932       }
8933       break;
8934
8935     case 4:
8936     case 5:
8937       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8938       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8939       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8940       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8941       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8942       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8943       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8944       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8945
8946
8947       if(shCount == 5) {
8948                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8949                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8950       }
8951       break;
8952     case 6:
8953       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8954       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8955       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8956       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8957
8958       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8959       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8960       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8961       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8962       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8963       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8964       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8965       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8966       break;
8967     case 7:
8968       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8969       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8970       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8973     }
8974   }
8975
8976 }
8977 /*-----------------------------------------------------------------*/
8978 /* shiftR2Left2Result - shift right two bytes from left to result  */
8979 /*-----------------------------------------------------------------*/
8980 static void shiftR2Left2Result (operand *left, int offl,
8981                                 operand *result, int offr,
8982                                 int shCount, int sign)
8983 {
8984   int same = pic16_sameRegs(AOP(result), AOP(left));
8985   int i;
8986   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8987
8988   if (same && (offl != offr)) { // shift right bytes
8989     if (offr < offl) {
8990        for(i=0;i<2;i++) {
8991          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8992          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8993        }
8994     } else { // just treat as different later on
8995                 same = 0;
8996     }
8997   }
8998
8999   switch(shCount) {
9000   case 0:
9001     break;
9002   case 1:
9003   case 2:
9004   case 3:
9005     if(sign)
9006       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9007     else
9008       emitCLRC;
9009
9010     if(same) {
9011       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9012       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9013     } else {
9014       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9015       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9016       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9017       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9018     }
9019
9020     while(--shCount) {
9021       if(sign)
9022                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9023       else
9024                 emitCLRC;
9025       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9026       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9027     }
9028     break;
9029   case 4:
9030   case 5:
9031     if(same) {
9032
9033       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9034       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9036
9037       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9038       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9039       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9040       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9041     } else {
9042       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9043       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9044       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9045
9046       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9047       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9048       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9049       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9050       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9051     }
9052
9053     if(shCount >=5) {
9054       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9055       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9056     }
9057
9058     if(sign) {
9059       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9060       pic16_emitpcode(POC_BTFSC, 
9061                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9062       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9063     }
9064
9065     break;
9066
9067   case 6:
9068     if(same) {
9069
9070       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9071       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9072
9073       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9074       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9075       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9076       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9077       if(sign) {
9078         pic16_emitpcode(POC_BTFSC, 
9079                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9080         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9081       }
9082       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9083       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9084       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9085       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9086     } else {
9087       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9088       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9089       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9090       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9091       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9092       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9093       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9094       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9095       if(sign) {
9096         pic16_emitpcode(POC_BTFSC, 
9097                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9098         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9099       }
9100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9101       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9102
9103         
9104     }
9105
9106     break;
9107   case 7:
9108     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9109     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9110     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9111     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9112     if(sign) {
9113       emitSKPNC;
9114       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9115     } else 
9116       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9117   }
9118 }
9119
9120
9121 /*-----------------------------------------------------------------*/
9122 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9123 /*-----------------------------------------------------------------*/
9124 static void shiftLLeftOrResult (operand *left, int offl,
9125                                 operand *result, int offr, int shCount)
9126 {
9127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9128
9129     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9130     /* shift left accumulator */
9131     AccLsh(shCount);
9132     /* or with result */
9133     /* back to result */
9134     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9135 }
9136
9137 /*-----------------------------------------------------------------*/
9138 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9139 /*-----------------------------------------------------------------*/
9140 static void shiftRLeftOrResult (operand *left, int offl,
9141                                 operand *result, int offr, int shCount)
9142 {
9143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9144     
9145     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9146     /* shift right accumulator */
9147     AccRsh(shCount, 1);
9148     /* or with result */
9149     /* back to result */
9150     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9151 }
9152
9153 /*-----------------------------------------------------------------*/
9154 /* genlshOne - left shift a one byte quantity by known count       */
9155 /*-----------------------------------------------------------------*/
9156 static void genlshOne (operand *result, operand *left, int shCount)
9157 {       
9158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9159     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9160 }
9161
9162 /*-----------------------------------------------------------------*/
9163 /* genlshTwo - left shift two bytes by known amount != 0           */
9164 /*-----------------------------------------------------------------*/
9165 static void genlshTwo (operand *result,operand *left, int shCount)
9166 {
9167     int size;
9168     
9169     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9170     size = pic16_getDataSize(result);
9171
9172     /* if shCount >= 8 */
9173     if (shCount >= 8) {
9174         shCount -= 8 ;
9175
9176         if (size > 1){
9177             if (shCount)
9178                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9179             else 
9180                 movLeft2Result(left, LSB, result, MSB16);
9181         }
9182         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9183     }
9184
9185     /*  1 <= shCount <= 7 */
9186     else {  
9187         if(size == 1)
9188             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9189         else 
9190             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9191     }
9192 }
9193
9194 /*-----------------------------------------------------------------*/
9195 /* shiftLLong - shift left one long from left to result            */
9196 /* offr = LSB or MSB16                                             */
9197 /*-----------------------------------------------------------------*/
9198 static void shiftLLong (operand *left, operand *result, int offr )
9199 {
9200     int size = AOP_SIZE(result);
9201     int same = pic16_sameRegs(AOP(left),AOP(result));
9202         int i;
9203
9204     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9205
9206         if (same && (offr == MSB16)) { //shift one byte
9207                 for(i=size-1;i>=MSB16;i--) {
9208                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9209                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9210                 }
9211         } else {
9212                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9213         }
9214         
9215     if (size > LSB+offr ){
9216                 if (same) {
9217                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9218                 } else {
9219                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9220                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9221                 }
9222          }
9223
9224     if(size > MSB16+offr){
9225                 if (same) {
9226                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9227                 } else {
9228                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9229                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9230                 }
9231     }
9232
9233     if(size > MSB24+offr){
9234                 if (same) {
9235                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9236                 } else {
9237                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9238                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9239                 }
9240     }
9241
9242     if(size > MSB32+offr){
9243                 if (same) {
9244                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9245                 } else {
9246                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9247                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9248                 }
9249     }
9250     if(offr != LSB)
9251                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9252
9253 }
9254
9255 /*-----------------------------------------------------------------*/
9256 /* genlshFour - shift four byte by a known amount != 0             */
9257 /*-----------------------------------------------------------------*/
9258 static void genlshFour (operand *result, operand *left, int shCount)
9259 {
9260     int size;
9261
9262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9263     size = AOP_SIZE(result);
9264
9265     /* if shifting more that 3 bytes */
9266     if (shCount >= 24 ) {
9267         shCount -= 24;
9268         if (shCount)
9269             /* lowest order of left goes to the highest
9270             order of the destination */
9271             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9272         else
9273             movLeft2Result(left, LSB, result, MSB32);
9274
9275                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9276                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9277                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9278
9279         return;
9280     }
9281
9282     /* more than two bytes */
9283     else if ( shCount >= 16 ) {
9284         /* lower order two bytes goes to higher order two bytes */
9285         shCount -= 16;
9286         /* if some more remaining */
9287         if (shCount)
9288             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9289         else {
9290             movLeft2Result(left, MSB16, result, MSB32);
9291             movLeft2Result(left, LSB, result, MSB24);
9292         }
9293                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9294                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9295         return;
9296     }    
9297
9298     /* if more than 1 byte */
9299     else if ( shCount >= 8 ) {
9300         /* lower order three bytes goes to higher order  three bytes */
9301         shCount -= 8;
9302         if(size == 2){
9303             if(shCount)
9304                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9305             else
9306                 movLeft2Result(left, LSB, result, MSB16);
9307         }
9308         else{   /* size = 4 */
9309             if(shCount == 0){
9310                 movLeft2Result(left, MSB24, result, MSB32);
9311                 movLeft2Result(left, MSB16, result, MSB24);
9312                 movLeft2Result(left, LSB, result, MSB16);
9313                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9314             }
9315             else if(shCount == 1)
9316                 shiftLLong(left, result, MSB16);
9317             else{
9318                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9319                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9320                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9321                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9322             }
9323         }
9324     }
9325
9326     /* 1 <= shCount <= 7 */
9327     else if(shCount <= 3)
9328     { 
9329         shiftLLong(left, result, LSB);
9330         while(--shCount >= 1)
9331             shiftLLong(result, result, LSB);
9332     }
9333     /* 3 <= shCount <= 7, optimize */
9334     else{
9335         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9336         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9337         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9338     }
9339 }
9340
9341 /*-----------------------------------------------------------------*/
9342 /* genLeftShiftLiteral - left shifting by known count              */
9343 /*-----------------------------------------------------------------*/
9344 void pic16_genLeftShiftLiteral (operand *left,
9345                                  operand *right,
9346                                  operand *result,
9347                                  iCode *ic)
9348 {    
9349     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9350     int size;
9351
9352     FENTRY;
9353     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9354     pic16_freeAsmop(right,NULL,ic,TRUE);
9355
9356     pic16_aopOp(left,ic,FALSE);
9357     pic16_aopOp(result,ic,FALSE);
9358
9359     size = getSize(operandType(result));
9360
9361 #if VIEW_SIZE
9362     pic16_emitcode("; shift left ","result %d, left %d",size,
9363              AOP_SIZE(left));
9364 #endif
9365
9366     /* I suppose that the left size >= result size */
9367     if(shCount == 0){
9368         while(size--){
9369             movLeft2Result(left, size, result, size);
9370         }
9371     }
9372
9373     else if(shCount >= (size * 8))
9374         while(size--)
9375             pic16_aopPut(AOP(result),zero,size);
9376     else{
9377         switch (size) {
9378             case 1:
9379                 genlshOne (result,left,shCount);
9380                 break;
9381
9382             case 2:
9383             case 3:
9384                 genlshTwo (result,left,shCount);
9385                 break;
9386
9387             case 4:
9388                 genlshFour (result,left,shCount);
9389                 break;
9390         }
9391     }
9392     pic16_freeAsmop(left,NULL,ic,TRUE);
9393     pic16_freeAsmop(result,NULL,ic,TRUE);
9394 }
9395
9396 /*-----------------------------------------------------------------*
9397  * genMultiAsm - repeat assembly instruction for size of register.
9398  * if endian == 1, then the high byte (i.e base address + size of 
9399  * register) is used first else the low byte is used first;
9400  *-----------------------------------------------------------------*/
9401 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9402 {
9403
9404   int offset = 0;
9405
9406   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9407
9408   if(!reg)
9409     return;
9410
9411   if(!endian) {
9412     endian = 1;
9413   } else {
9414     endian = -1;
9415     offset = size-1;
9416   }
9417
9418   while(size--) {
9419     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9420     offset += endian;
9421   }
9422
9423 }
9424 /*-----------------------------------------------------------------*/
9425 /* genLeftShift - generates code for left shifting                 */
9426 /*-----------------------------------------------------------------*/
9427 static void genLeftShift (iCode *ic)
9428 {
9429   operand *left,*right, *result;
9430   int size, offset;
9431 //  char *l;
9432   symbol *tlbl , *tlbl1;
9433   pCodeOp *pctemp;
9434
9435   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9436
9437   right = IC_RIGHT(ic);
9438   left  = IC_LEFT(ic);
9439   result = IC_RESULT(ic);
9440
9441   pic16_aopOp(right,ic,FALSE);
9442
9443   /* if the shift count is known then do it 
9444      as efficiently as possible */
9445   if (AOP_TYPE(right) == AOP_LIT) {
9446     pic16_genLeftShiftLiteral (left,right,result,ic);
9447     return ;
9448   }
9449
9450   /* shift count is unknown then we have to form
9451    * a loop. Get the loop count in WREG : Note: we take
9452    * only the lower order byte since shifting
9453    * more than 32 bits make no sense anyway, ( the
9454    * largest size of an object can be only 32 bits ) */
9455   
9456   pic16_aopOp(left,ic,FALSE);
9457   pic16_aopOp(result,ic,FALSE);
9458
9459   /* now move the left to the result if they are not the
9460    * same, and if size > 1,
9461    * and if right is not same to result (!!!) -- VR */
9462   if (!pic16_sameRegs(AOP(left),AOP(result))
9463       && (AOP_SIZE(result) > 1)) {
9464
9465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9466
9467     size = AOP_SIZE(result);
9468     offset=0;
9469     while (size--) {
9470
9471 #if 0
9472       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9473       if (*l == '@' && (IS_AOP_PREG(result))) {
9474
9475           pic16_emitcode("mov","a,%s",l);
9476           pic16_aopPut(AOP(result),"a",offset);
9477       } else
9478 #endif
9479       {
9480         /* we don't know if left is a literal or a register, take care -- VR */
9481         mov2f(AOP(result), AOP(left), offset);
9482       }
9483       offset++;
9484     }
9485   }
9486
9487   size = AOP_SIZE(result);
9488
9489   /* if it is only one byte then */
9490   if (size == 1) {
9491     if(optimized_for_speed) {
9492       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9493       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9494       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9495       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9496       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9497       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9498       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9499       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9500       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9501       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9502       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9503       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9504     } else {
9505
9506       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9507
9508       tlbl = newiTempLabel(NULL);
9509
9510 #if 1
9511       /* this is already done, why change it? */
9512       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9513                 mov2f(AOP(result), AOP(left), 0);
9514       }
9515 #endif
9516
9517       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9518       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9519       pic16_emitpLabel(tlbl->key);
9520       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9521       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9522       emitSKPC;
9523       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9524     }
9525     goto release ;
9526   }
9527     
9528   if (pic16_sameRegs(AOP(left),AOP(result))) {
9529
9530     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9531     
9532     tlbl = newiTempLabel(NULL);
9533     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9534     genMultiAsm(POC_RRCF, result, size,1);
9535     pic16_emitpLabel(tlbl->key);
9536     genMultiAsm(POC_RLCF, result, size,0);
9537     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9538     emitSKPC;
9539     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9540     goto release;
9541   }
9542
9543   //tlbl = newiTempLabel(NULL);
9544   //offset = 0 ;   
9545   //tlbl1 = newiTempLabel(NULL);
9546
9547   //reAdjustPreg(AOP(result));    
9548     
9549   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9550   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9551   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9552   //MOVA(l);
9553   //pic16_emitcode("add","a,acc");         
9554   //pic16_aopPut(AOP(result),"a",offset++);
9555   //while (--size) {
9556   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9557   //  MOVA(l);
9558   //  pic16_emitcode("rlc","a");         
9559   //  pic16_aopPut(AOP(result),"a",offset++);
9560   //}
9561   //reAdjustPreg(AOP(result));
9562
9563   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9564   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9565
9566
9567   tlbl = newiTempLabel(NULL);
9568   tlbl1= newiTempLabel(NULL);
9569
9570   size = AOP_SIZE(result);
9571   offset = 1;
9572
9573   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9574
9575   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9576
9577   /* offset should be 0, 1 or 3 */
9578   
9579   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9580   emitSKPNZ;
9581   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9582
9583   pic16_emitpcode(POC_MOVWF, pctemp);
9584
9585
9586   pic16_emitpLabel(tlbl->key);
9587
9588   emitCLRC;
9589   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9590   while(--size)
9591     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9592
9593   pic16_emitpcode(POC_DECFSZ,  pctemp);
9594   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9595   pic16_emitpLabel(tlbl1->key);
9596
9597   pic16_popReleaseTempReg(pctemp,1);
9598
9599
9600  release:
9601   pic16_freeAsmop (right,NULL,ic,TRUE);
9602   pic16_freeAsmop(left,NULL,ic,TRUE);
9603   pic16_freeAsmop(result,NULL,ic,TRUE);
9604 }
9605
9606
9607
9608 #if 0
9609 #error old code (left here for reference)
9610 /*-----------------------------------------------------------------*/
9611 /* genLeftShift - generates code for left shifting                 */
9612 /*-----------------------------------------------------------------*/
9613 static void genLeftShift (iCode *ic)
9614 {
9615   operand *left,*right, *result;
9616   int size, offset;
9617   char *l;
9618   symbol *tlbl , *tlbl1;
9619   pCodeOp *pctemp;
9620
9621   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9622
9623   right = IC_RIGHT(ic);
9624   left  = IC_LEFT(ic);
9625   result = IC_RESULT(ic);
9626
9627   pic16_aopOp(right,ic,FALSE);
9628
9629   /* if the shift count is known then do it 
9630      as efficiently as possible */
9631   if (AOP_TYPE(right) == AOP_LIT) {
9632     pic16_genLeftShiftLiteral (left,right,result,ic);
9633     return ;
9634   }
9635
9636   /* shift count is unknown then we have to form 
9637      a loop get the loop count in B : Note: we take
9638      only the lower order byte since shifting
9639      more that 32 bits make no sense anyway, ( the
9640      largest size of an object can be only 32 bits ) */  
9641
9642     
9643   pic16_aopOp(left,ic,FALSE);
9644   pic16_aopOp(result,ic,FALSE);
9645
9646   /* now move the left to the result if they are not the
9647      same */
9648   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9649       AOP_SIZE(result) > 1) {
9650
9651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9652
9653     size = AOP_SIZE(result);
9654     offset=0;
9655     while (size--) {
9656       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9657       if (*l == '@' && (IS_AOP_PREG(result))) {
9658
9659         pic16_emitcode("mov","a,%s",l);
9660         pic16_aopPut(AOP(result),"a",offset);
9661       } else {
9662
9663         /* we don't know if left is a literal or a register, take care -- VR */
9664         mov2f(AOP(result), AOP(left), offset);
9665       }
9666       offset++;
9667     }
9668   }
9669
9670   size = AOP_SIZE(result);
9671
9672   /* if it is only one byte then */
9673   if (size == 1) {
9674     if(optimized_for_speed) {
9675       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9676       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9677       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9678       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9679       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9680       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9681       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9682       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9683       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9684       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9685       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9686       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9687     } else {
9688
9689       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9690
9691       tlbl = newiTempLabel(NULL);
9692       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9693                 mov2f(AOP(result), AOP(left), 0);
9694                 
9695 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9696 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9697       }
9698
9699       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9700       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9701       pic16_emitpLabel(tlbl->key);
9702       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9703       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9704       emitSKPC;
9705       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9706     }
9707     goto release ;
9708   }
9709     
9710   if (pic16_sameRegs(AOP(left),AOP(result))) {
9711
9712     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9713     
9714     tlbl = newiTempLabel(NULL);
9715     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9716     genMultiAsm(POC_RRCF, result, size,1);
9717     pic16_emitpLabel(tlbl->key);
9718     genMultiAsm(POC_RLCF, result, size,0);
9719     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9720     emitSKPC;
9721     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9722     goto release;
9723   }
9724
9725   //tlbl = newiTempLabel(NULL);
9726   //offset = 0 ;   
9727   //tlbl1 = newiTempLabel(NULL);
9728
9729   //reAdjustPreg(AOP(result));    
9730     
9731   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9732   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9733   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9734   //MOVA(l);
9735   //pic16_emitcode("add","a,acc");         
9736   //pic16_aopPut(AOP(result),"a",offset++);
9737   //while (--size) {
9738   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9739   //  MOVA(l);
9740   //  pic16_emitcode("rlc","a");         
9741   //  pic16_aopPut(AOP(result),"a",offset++);
9742   //}
9743   //reAdjustPreg(AOP(result));
9744
9745   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9746   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9747
9748
9749   tlbl = newiTempLabel(NULL);
9750   tlbl1= newiTempLabel(NULL);
9751
9752   size = AOP_SIZE(result);
9753   offset = 1;
9754
9755   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9756
9757   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9758
9759   /* offset should be 0, 1 or 3 */
9760   
9761   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9762   emitSKPNZ;
9763   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9764
9765   pic16_emitpcode(POC_MOVWF, pctemp);
9766
9767
9768   pic16_emitpLabel(tlbl->key);
9769
9770   emitCLRC;
9771   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9772   while(--size)
9773     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9774
9775   pic16_emitpcode(POC_DECFSZ,  pctemp);
9776   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9777   pic16_emitpLabel(tlbl1->key);
9778
9779   pic16_popReleaseTempReg(pctemp,1);
9780
9781
9782  release:
9783   pic16_freeAsmop (right,NULL,ic,TRUE);
9784   pic16_freeAsmop(left,NULL,ic,TRUE);
9785   pic16_freeAsmop(result,NULL,ic,TRUE);
9786 }
9787 #endif
9788
9789 /*-----------------------------------------------------------------*/
9790 /* genrshOne - right shift a one byte quantity by known count      */
9791 /*-----------------------------------------------------------------*/
9792 static void genrshOne (operand *result, operand *left,
9793                        int shCount, int sign)
9794 {
9795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9796     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9797 }
9798
9799 /*-----------------------------------------------------------------*/
9800 /* genrshTwo - right shift two bytes by known amount != 0          */
9801 /*-----------------------------------------------------------------*/
9802 static void genrshTwo (operand *result,operand *left,
9803                        int shCount, int sign)
9804 {
9805   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9806   /* if shCount >= 8 */
9807   if (shCount >= 8) {
9808     shCount -= 8 ;
9809     if (shCount)
9810       shiftR1Left2Result(left, MSB16, result, LSB,
9811                          shCount, sign);
9812     else
9813       movLeft2Result(left, MSB16, result, LSB);
9814
9815     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9816
9817     if(sign) {
9818       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9819       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9820     }
9821   }
9822
9823   /*  1 <= shCount <= 7 */
9824   else
9825     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9826 }
9827
9828 /*-----------------------------------------------------------------*/
9829 /* shiftRLong - shift right one long from left to result           */
9830 /* offl = LSB or MSB16                                             */
9831 /*-----------------------------------------------------------------*/
9832 static void shiftRLong (operand *left, int offl,
9833                         operand *result, int sign)
9834 {
9835     int size = AOP_SIZE(result);
9836     int same = pic16_sameRegs(AOP(left),AOP(result));
9837     int i;
9838     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9839
9840         if (same && (offl == MSB16)) { //shift one byte right
9841                 for(i=MSB16;i<size;i++) {
9842                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9843                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9844                 }
9845         }
9846
9847     if(sign)
9848                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9849         else
9850                 emitCLRC;
9851
9852         if (same) {
9853                 if (offl == LSB)
9854                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9855         } else {
9856         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9857         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9858         }
9859
9860     if(offl == MSB16) {
9861         /* add sign of "a" */
9862         pic16_addSign(result, MSB32, sign);
9863         }
9864
9865         if (same) {
9866         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9867         } else {
9868         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9869         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9870         }
9871         
9872         if (same) {
9873         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9874         } else {
9875         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9876         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9877         }
9878
9879         if (same) {
9880         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9881         } else {
9882         if(offl == LSB){
9883                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9884                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9885         }
9886         }
9887 }
9888
9889 /*-----------------------------------------------------------------*/
9890 /* genrshFour - shift four byte by a known amount != 0             */
9891 /*-----------------------------------------------------------------*/
9892 static void genrshFour (operand *result, operand *left,
9893                         int shCount, int sign)
9894 {
9895   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9896   /* if shifting more that 3 bytes */
9897   if(shCount >= 24 ) {
9898     shCount -= 24;
9899     if(shCount)
9900       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9901     else
9902       movLeft2Result(left, MSB32, result, LSB);
9903
9904     pic16_addSign(result, MSB16, sign);
9905   }
9906   else if(shCount >= 16){
9907     shCount -= 16;
9908     if(shCount)
9909       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9910     else{
9911       movLeft2Result(left, MSB24, result, LSB);
9912       movLeft2Result(left, MSB32, result, MSB16);
9913     }
9914     pic16_addSign(result, MSB24, sign);
9915   }
9916   else if(shCount >= 8){
9917     shCount -= 8;
9918     if(shCount == 1)
9919       shiftRLong(left, MSB16, result, sign);
9920     else if(shCount == 0){
9921       movLeft2Result(left, MSB16, result, LSB);
9922       movLeft2Result(left, MSB24, result, MSB16);
9923       movLeft2Result(left, MSB32, result, MSB24);
9924       pic16_addSign(result, MSB32, sign);
9925     }
9926     else{ //shcount >= 2
9927       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9928       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9929       /* the last shift is signed */
9930       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9931       pic16_addSign(result, MSB32, sign);
9932     }
9933   }
9934   else{   /* 1 <= shCount <= 7 */
9935     if(shCount <= 2){
9936       shiftRLong(left, LSB, result, sign);
9937       if(shCount == 2)
9938         shiftRLong(result, LSB, result, sign);
9939     }
9940     else{
9941       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9942       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9943       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9944     }
9945   }
9946 }
9947
9948 /*-----------------------------------------------------------------*/
9949 /* genRightShiftLiteral - right shifting by known count            */
9950 /*-----------------------------------------------------------------*/
9951 static void genRightShiftLiteral (operand *left,
9952                                   operand *right,
9953                                   operand *result,
9954                                   iCode *ic,
9955                                   int sign)
9956 {    
9957   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9958   int lsize,res_size;
9959
9960   pic16_freeAsmop(right,NULL,ic,TRUE);
9961
9962   pic16_aopOp(left,ic,FALSE);
9963   pic16_aopOp(result,ic,FALSE);
9964
9965   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9966
9967 #if VIEW_SIZE
9968   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9969                  AOP_SIZE(left));
9970 #endif
9971
9972   lsize = pic16_getDataSize(left);
9973   res_size = pic16_getDataSize(result);
9974   /* test the LEFT size !!! */
9975
9976   /* I suppose that the left size >= result size */
9977   if(shCount == 0){
9978     while(res_size--)
9979       movLeft2Result(left, lsize, result, res_size);
9980   }
9981
9982   else if(shCount >= (lsize * 8)){
9983
9984     if(res_size == 1) {
9985       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9986       if(sign) {
9987         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9988         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9989       }
9990     } else {
9991
9992       if(sign) {
9993         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9994         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9995         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9996         while(res_size--)
9997           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9998
9999       } else {
10000
10001         while(res_size--)
10002           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10003       }
10004     }
10005   } else {
10006
10007     switch (res_size) {
10008     case 1:
10009       genrshOne (result,left,shCount,sign);
10010       break;
10011
10012     case 2:
10013       genrshTwo (result,left,shCount,sign);
10014       break;
10015
10016     case 4:
10017       genrshFour (result,left,shCount,sign);
10018       break;
10019     default :
10020       break;
10021     }
10022
10023   }
10024
10025   pic16_freeAsmop(left,NULL,ic,TRUE);
10026   pic16_freeAsmop(result,NULL,ic,TRUE);
10027 }
10028
10029 /*-----------------------------------------------------------------*/
10030 /* genSignedRightShift - right shift of signed number              */
10031 /*-----------------------------------------------------------------*/
10032 static void genSignedRightShift (iCode *ic)
10033 {
10034   operand *right, *left, *result;
10035   int size, offset;
10036   //  char *l;
10037   symbol *tlbl, *tlbl1 ;
10038   pCodeOp *pctemp;
10039
10040   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10041
10042   /* we do it the hard way put the shift count in b
10043      and loop thru preserving the sign */
10044   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10045
10046   right = IC_RIGHT(ic);
10047   left  = IC_LEFT(ic);
10048   result = IC_RESULT(ic);
10049
10050   pic16_aopOp(right,ic,FALSE);  
10051   pic16_aopOp(left,ic,FALSE);
10052   pic16_aopOp(result,ic,FALSE);
10053
10054
10055   if ( AOP_TYPE(right) == AOP_LIT) {
10056     genRightShiftLiteral (left,right,result,ic,1);
10057     return ;
10058   }
10059   /* shift count is unknown then we have to form 
10060      a loop get the loop count in B : Note: we take
10061      only the lower order byte since shifting
10062      more that 32 bits make no sense anyway, ( the
10063      largest size of an object can be only 32 bits ) */  
10064
10065   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10066   //pic16_emitcode("inc","b");
10067   //pic16_freeAsmop (right,NULL,ic,TRUE);
10068   //pic16_aopOp(left,ic,FALSE);
10069   //pic16_aopOp(result,ic,FALSE);
10070
10071   /* now move the left to the result if they are not the
10072      same */
10073   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10074       AOP_SIZE(result) > 1) {
10075
10076     size = AOP_SIZE(result);
10077     offset=0;
10078     while (size--) { 
10079       /*
10080         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10081         if (*l == '@' && IS_AOP_PREG(result)) {
10082
10083         pic16_emitcode("mov","a,%s",l);
10084         pic16_aopPut(AOP(result),"a",offset);
10085         } else
10086         pic16_aopPut(AOP(result),l,offset);
10087       */
10088       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10089       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10090
10091       offset++;
10092     }
10093   }
10094
10095   /* mov the highest order bit to OVR */    
10096   tlbl = newiTempLabel(NULL);
10097   tlbl1= newiTempLabel(NULL);
10098
10099   size = AOP_SIZE(result);
10100   offset = size - 1;
10101
10102   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10103
10104   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10105
10106   /* offset should be 0, 1 or 3 */
10107   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10108   emitSKPNZ;
10109   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10110
10111   pic16_emitpcode(POC_MOVWF, pctemp);
10112
10113
10114   pic16_emitpLabel(tlbl->key);
10115
10116   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10117   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10118
10119   while(--size) {
10120     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10121   }
10122
10123   pic16_emitpcode(POC_DECFSZ,  pctemp);
10124   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10125   pic16_emitpLabel(tlbl1->key);
10126
10127   pic16_popReleaseTempReg(pctemp,1);
10128 #if 0
10129   size = AOP_SIZE(result);
10130   offset = size - 1;
10131   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10132   pic16_emitcode("rlc","a");
10133   pic16_emitcode("mov","ov,c");
10134   /* if it is only one byte then */
10135   if (size == 1) {
10136     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10137     MOVA(l);
10138     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10139     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10140     pic16_emitcode("mov","c,ov");
10141     pic16_emitcode("rrc","a");
10142     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10143     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10144     pic16_aopPut(AOP(result),"a",0);
10145     goto release ;
10146   }
10147
10148   reAdjustPreg(AOP(result));
10149   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10150   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10151   pic16_emitcode("mov","c,ov");
10152   while (size--) {
10153     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10154     MOVA(l);
10155     pic16_emitcode("rrc","a");         
10156     pic16_aopPut(AOP(result),"a",offset--);
10157   }
10158   reAdjustPreg(AOP(result));
10159   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10160   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10161
10162  release:
10163 #endif
10164
10165   pic16_freeAsmop(left,NULL,ic,TRUE);
10166   pic16_freeAsmop(result,NULL,ic,TRUE);
10167   pic16_freeAsmop(right,NULL,ic,TRUE);
10168 }
10169
10170 /*-----------------------------------------------------------------*/
10171 /* genRightShift - generate code for right shifting                */
10172 /*-----------------------------------------------------------------*/
10173 static void genRightShift (iCode *ic)
10174 {
10175     operand *right, *left, *result;
10176     sym_link *letype ;
10177     int size, offset;
10178     char *l;
10179     symbol *tlbl, *tlbl1 ;
10180
10181     /* if signed then we do it the hard way preserve the
10182     sign bit moving it inwards */
10183     letype = getSpec(operandType(IC_LEFT(ic)));
10184     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10185
10186     if (!SPEC_USIGN(letype)) {
10187         genSignedRightShift (ic);
10188         return ;
10189     }
10190
10191     /* signed & unsigned types are treated the same : i.e. the
10192     signed is NOT propagated inwards : quoting from the
10193     ANSI - standard : "for E1 >> E2, is equivalent to division
10194     by 2**E2 if unsigned or if it has a non-negative value,
10195     otherwise the result is implementation defined ", MY definition
10196     is that the sign does not get propagated */
10197
10198     right = IC_RIGHT(ic);
10199     left  = IC_LEFT(ic);
10200     result = IC_RESULT(ic);
10201
10202     pic16_aopOp(right,ic,FALSE);
10203
10204     /* if the shift count is known then do it 
10205     as efficiently as possible */
10206     if (AOP_TYPE(right) == AOP_LIT) {
10207         genRightShiftLiteral (left,right,result,ic, 0);
10208         return ;
10209     }
10210
10211     /* shift count is unknown then we have to form 
10212     a loop get the loop count in B : Note: we take
10213     only the lower order byte since shifting
10214     more that 32 bits make no sense anyway, ( the
10215     largest size of an object can be only 32 bits ) */  
10216
10217     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10218     pic16_emitcode("inc","b");
10219     pic16_aopOp(left,ic,FALSE);
10220     pic16_aopOp(result,ic,FALSE);
10221
10222     /* now move the left to the result if they are not the
10223     same */
10224     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10225         AOP_SIZE(result) > 1) {
10226
10227         size = AOP_SIZE(result);
10228         offset=0;
10229         while (size--) {
10230             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10231             if (*l == '@' && IS_AOP_PREG(result)) {
10232
10233                 pic16_emitcode("mov","a,%s",l);
10234                 pic16_aopPut(AOP(result),"a",offset);
10235             } else
10236                 pic16_aopPut(AOP(result),l,offset);
10237             offset++;
10238         }
10239     }
10240
10241     tlbl = newiTempLabel(NULL);
10242     tlbl1= newiTempLabel(NULL);
10243     size = AOP_SIZE(result);
10244     offset = size - 1;
10245
10246     /* if it is only one byte then */
10247     if (size == 1) {
10248
10249       tlbl = newiTempLabel(NULL);
10250       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10251         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10252         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10253       }
10254
10255       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10256       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10257       pic16_emitpLabel(tlbl->key);
10258       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10259       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10260       emitSKPC;
10261       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10262
10263       goto release ;
10264     }
10265
10266     reAdjustPreg(AOP(result));
10267     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10268     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10269     CLRC;
10270     while (size--) {
10271         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10272         MOVA(l);
10273         pic16_emitcode("rrc","a");         
10274         pic16_aopPut(AOP(result),"a",offset--);
10275     }
10276     reAdjustPreg(AOP(result));
10277
10278     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10279     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10280
10281 release:
10282     pic16_freeAsmop(left,NULL,ic,TRUE);
10283     pic16_freeAsmop (right,NULL,ic,TRUE);
10284     pic16_freeAsmop(result,NULL,ic,TRUE);
10285 }
10286
10287
10288 void pic16_loadFSR0(operand *op)
10289 {
10290         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10291 }
10292
10293 /*-----------------------------------------------------------------*/
10294 /* genUnpackBits - generates code for unpacking bits               */
10295 /*-----------------------------------------------------------------*/
10296 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10297 {    
10298   int shCnt ;
10299   int rlen = 0 ;
10300   sym_link *etype, *letype;
10301   int blen=0, bstr=0;
10302   int lbstr;
10303   int offset = 0 ;
10304
10305     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10306     etype = getSpec(operandType(result));
10307     letype = getSpec(operandType(left));
10308     
10309 //    if(IS_BITFIELD(etype)) {
10310       blen = SPEC_BLEN(etype);
10311       bstr = SPEC_BSTR(etype);
10312 //    }
10313
10314     lbstr = SPEC_BSTR( letype );
10315
10316 #if 1
10317     if((blen == 1) && (bstr < 8)) {
10318       /* it is a single bit, so use the appropriate bit instructions */
10319       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10320
10321       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10322       
10323       if((ptype == POINTER) && (result)) {
10324         /* workaround to reduce the extra lfsr instruction */
10325         pic16_emitpcode(POC_BTFSC,
10326               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10327       } else {
10328         pic16_emitpcode(POC_BTFSC,
10329               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10330       }
10331         
10332       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10333
10334       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10335       return;
10336     }
10337
10338 #endif
10339
10340         /* the following call to pic16_loadFSR0 is temporary until
10341          * optimization to handle single bit assignments is added
10342          * to the function. Until then use the old safe way! -- VR */
10343         pic16_loadFSR0( left );
10344  
10345         /* read the first byte  */
10346         switch (ptype) {
10347                 case POINTER:
10348                 case IPOINTER:
10349                 case PPOINTER:
10350                 case FPOINTER:
10351                 case GPOINTER:
10352                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10353                         break;
10354                 case CPOINTER:
10355                         pic16_emitcode("clr","a");
10356                         pic16_emitcode("movc","a","@a+dptr");
10357                         break;
10358         }
10359         
10360
10361         /* if we have bitdisplacement then it fits   */
10362         /* into this byte completely or if length is */
10363         /* less than a byte                          */
10364         if ((shCnt = SPEC_BSTR(etype)) || 
10365                 (SPEC_BLEN(etype) <= 8))  {
10366
10367                 /* shift right acc */
10368                 AccRsh(shCnt, 0);
10369
10370                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10371                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10372
10373 /* VR -- normally I would use the following, but since we use the hack,
10374  * to avoid the masking from AccRsh, why not mask it right now? */
10375
10376 /*
10377                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10378 */
10379
10380                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10381           return ;
10382         }
10383
10384
10385
10386         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10387         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10388         exit(-1);
10389
10390     /* bit field did not fit in a byte  */
10391     rlen = SPEC_BLEN(etype) - 8;
10392     pic16_aopPut(AOP(result),"a",offset++);
10393
10394     while (1)  {
10395
10396         switch (ptype) {
10397         case POINTER:
10398         case IPOINTER:
10399             pic16_emitcode("inc","%s",rname);
10400             pic16_emitcode("mov","a,@%s",rname);
10401             break;
10402             
10403         case PPOINTER:
10404             pic16_emitcode("inc","%s",rname);
10405             pic16_emitcode("movx","a,@%s",rname);
10406             break;
10407
10408         case FPOINTER:
10409             pic16_emitcode("inc","dptr");
10410             pic16_emitcode("movx","a,@dptr");
10411             break;
10412             
10413         case CPOINTER:
10414             pic16_emitcode("clr","a");
10415             pic16_emitcode("inc","dptr");
10416             pic16_emitcode("movc","a","@a+dptr");
10417             break;
10418             
10419         case GPOINTER:
10420             pic16_emitcode("inc","dptr");
10421             pic16_emitcode("lcall","__gptrget");
10422             break;
10423         }
10424
10425         rlen -= 8;            
10426         /* if we are done */
10427         if ( rlen <= 0 )
10428             break ;
10429         
10430         pic16_aopPut(AOP(result),"a",offset++);
10431                               
10432     }
10433     
10434     if (rlen) {
10435         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10436         pic16_aopPut(AOP(result),"a",offset);          
10437     }
10438     
10439     return ;
10440 }
10441
10442
10443 static void genDataPointerGet(operand *left,
10444                               operand *result,
10445                               iCode *ic)
10446 {
10447   int size, offset = 0, leoffset=0 ;
10448
10449         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10450         pic16_aopOp(result, ic, FALSE);
10451
10452         size = AOP_SIZE(result);
10453 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10454
10455
10456 #if 0
10457         /* The following tests may save a redudant movff instruction when
10458          * accessing unions */
10459          
10460         /* if they are the same */
10461         if (operandsEqu (left, result)) {
10462                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10463                 goto release;
10464         }
10465 #endif
10466
10467 #if 0
10468         /* if they are the same registers */
10469         if (pic16_sameRegs(AOP(left),AOP(result))) {
10470                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10471                 goto release;
10472         }
10473 #endif
10474
10475 #if 1
10476         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10477                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10478                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10479                 goto release;
10480         }
10481 #endif
10482
10483
10484 #if 0
10485         if ( AOP_TYPE(left) == AOP_PCODE) {
10486                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10487                                 AOP(left)->aopu.pcop->name,
10488                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10489                                 PCOR(AOP(left)->aopu.pcop)->instance:
10490                                 PCOI(AOP(left)->aopu.pcop)->offset);
10491         }
10492 #endif
10493
10494         if(AOP(left)->aopu.pcop->type == PO_DIR)
10495                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10496
10497         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10498
10499         while (size--) {
10500                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10501                 
10502                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10503                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10504                         pic16_mov2w(AOP(left), offset); // patch 8
10505                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10506                 } else {
10507                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10508                                 pic16_popGet(AOP(left), offset), //patch 8
10509                                 pic16_popGet(AOP(result), offset)));
10510                 }
10511
10512                 offset++;
10513                 leoffset++;
10514         }
10515
10516 release:
10517     pic16_freeAsmop(result,NULL,ic,TRUE);
10518 }
10519
10520
10521
10522 /*-----------------------------------------------------------------*/
10523 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10524 /*-----------------------------------------------------------------*/
10525 static void genNearPointerGet (operand *left, 
10526                                operand *result, 
10527                                iCode *ic)
10528 {
10529   asmop *aop = NULL;
10530   //regs *preg = NULL ;
10531   sym_link *rtype, *retype;
10532   sym_link *ltype = operandType(left);    
10533
10534     FENTRY;
10535     
10536     rtype = operandType(result);
10537     retype= getSpec(rtype);
10538     
10539     pic16_aopOp(left,ic,FALSE);
10540
10541 //    pic16_DumpOp("(left)",left);
10542 //    pic16_DumpOp("(result)",result);
10543
10544     /* if left is rematerialisable and
10545      * result is not bit variable type and
10546      * the left is pointer to data space i.e
10547      * lower 128 bytes of space */
10548     
10549     if (AOP_TYPE(left) == AOP_PCODE
10550       && !IS_BITFIELD(retype)
10551       && DCL_TYPE(ltype) == POINTER) {
10552
10553         genDataPointerGet (left,result,ic);
10554         pic16_freeAsmop(left, NULL, ic, TRUE);
10555         return ;
10556     }
10557     
10558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10559
10560     /* if the value is already in a pointer register
10561      * then don't need anything more */
10562     if (!AOP_INPREG(AOP(left))) {
10563       /* otherwise get a free pointer register */
10564       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10565                 
10566       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10567       /* bitfields will be handled by genUnpackBits */
10568       if(!IS_BITFIELD(retype)) {
10569
10570         if(is_LitAOp( AOP(left) )) {
10571           pic16_loadFSR0( left );
10572         } else {
10573             // set up FSR0 with address from left
10574             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10575             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10576         }
10577       }
10578     }
10579 //    else
10580 //    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10581     
10582     pic16_aopOp (result,ic,FALSE);
10583     
10584     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10585
10586     /* if bitfield then unpack the bits */
10587     if (IS_BITFIELD(retype)) 
10588       genUnpackBits (result, left, NULL, POINTER);
10589     else {
10590       /* we have can just get the values */
10591       int size = AOP_SIZE(result);
10592       int offset = 0;   
10593         
10594       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10595
10596       /* fsr0 is loaded already -- VR */
10597 //      pic16_loadFSR0( left );
10598
10599 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10600 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10601       while(size--) {
10602         if(size) {
10603           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10604                 pic16_popGet(AOP(result), offset++)));
10605         } else {
10606           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10607                 pic16_popGet(AOP(result), offset++)));
10608         }
10609       }
10610 #if 0
10611 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10612 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10613       if(size)
10614         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10615 #endif
10616 /*
10617         while (size--) {
10618             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10619
10620                 pic16_emitcode("mov","a,@%s",rname);
10621                 pic16_aopPut(AOP(result),"a",offset);
10622             } else {
10623                 sprintf(buffer,"@%s",rname);
10624                 pic16_aopPut(AOP(result),buffer,offset);
10625             }
10626             offset++ ;
10627             if (size)
10628                 pic16_emitcode("inc","%s",rname);
10629         }
10630 */
10631     }
10632
10633     /* now some housekeeping stuff */
10634     if (aop) {
10635       /* we had to allocate for this iCode */
10636       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10637       pic16_freeAsmop(NULL,aop,ic,TRUE);
10638     } else { 
10639       /* we did not allocate which means left
10640        * already in a pointer register, then
10641        * if size > 0 && this could be used again
10642        * we have to point it back to where it 
10643        * belongs */
10644       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10645       if (AOP_SIZE(result) > 1
10646         && !OP_SYMBOL(left)->remat
10647         && ( OP_SYMBOL(left)->liveTo > ic->seq
10648             || ic->depth )) {
10649 //        int size = AOP_SIZE(result) - 1;
10650 //        while (size--)
10651 //          pic16_emitcode("dec","%s",rname);
10652         }
10653     }
10654
10655     /* done */
10656     pic16_freeAsmop(left,NULL,ic,TRUE);
10657     pic16_freeAsmop(result,NULL,ic,TRUE);
10658 }
10659
10660 /*-----------------------------------------------------------------*/
10661 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10662 /*-----------------------------------------------------------------*/
10663 static void genPagedPointerGet (operand *left, 
10664                                operand *result, 
10665                                iCode *ic)
10666 {
10667     asmop *aop = NULL;
10668     regs *preg = NULL ;
10669     char *rname ;
10670     sym_link *rtype, *retype;    
10671
10672     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10673
10674     rtype = operandType(result);
10675     retype= getSpec(rtype);
10676     
10677     pic16_aopOp(left,ic,FALSE);
10678
10679   /* if the value is already in a pointer register
10680        then don't need anything more */
10681     if (!AOP_INPREG(AOP(left))) {
10682         /* otherwise get a free pointer register */
10683         aop = newAsmop(0);
10684         preg = getFreePtr(ic,&aop,FALSE);
10685         pic16_emitcode("mov","%s,%s",
10686                 preg->name,
10687                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10688         rname = preg->name ;
10689     } else
10690         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10691     
10692     pic16_freeAsmop(left,NULL,ic,TRUE);
10693     pic16_aopOp (result,ic,FALSE);
10694
10695     /* if bitfield then unpack the bits */
10696     if (IS_BITFIELD(retype)) 
10697         genUnpackBits (result,left,rname,PPOINTER);
10698     else {
10699         /* we have can just get the values */
10700         int size = AOP_SIZE(result);
10701         int offset = 0 ;        
10702         
10703         while (size--) {
10704             
10705             pic16_emitcode("movx","a,@%s",rname);
10706             pic16_aopPut(AOP(result),"a",offset);
10707             
10708             offset++ ;
10709             
10710             if (size)
10711                 pic16_emitcode("inc","%s",rname);
10712         }
10713     }
10714
10715     /* now some housekeeping stuff */
10716     if (aop) {
10717         /* we had to allocate for this iCode */
10718         pic16_freeAsmop(NULL,aop,ic,TRUE);
10719     } else { 
10720         /* we did not allocate which means left
10721            already in a pointer register, then
10722            if size > 0 && this could be used again
10723            we have to point it back to where it 
10724            belongs */
10725         if (AOP_SIZE(result) > 1 &&
10726             !OP_SYMBOL(left)->remat &&
10727             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10728               ic->depth )) {
10729             int size = AOP_SIZE(result) - 1;
10730             while (size--)
10731                 pic16_emitcode("dec","%s",rname);
10732         }
10733     }
10734
10735     /* done */
10736     pic16_freeAsmop(result,NULL,ic,TRUE);
10737     
10738         
10739 }
10740
10741 /*-----------------------------------------------------------------*/
10742 /* genFarPointerGet - gget value from far space                    */
10743 /*-----------------------------------------------------------------*/
10744 static void genFarPointerGet (operand *left,
10745                               operand *result, iCode *ic)
10746 {
10747     int size, offset ;
10748     sym_link *retype = getSpec(operandType(result));
10749
10750     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10751
10752     pic16_aopOp(left,ic,FALSE);
10753
10754     /* if the operand is already in dptr 
10755     then we do nothing else we move the value to dptr */
10756     if (AOP_TYPE(left) != AOP_STR) {
10757         /* if this is remateriazable */
10758         if (AOP_TYPE(left) == AOP_IMMD)
10759             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10760         else { /* we need to get it byte by byte */
10761             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10762             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10763             if (options.model == MODEL_FLAT24)
10764             {
10765                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10766             }
10767         }
10768     }
10769     /* so dptr know contains the address */
10770     pic16_freeAsmop(left,NULL,ic,TRUE);
10771     pic16_aopOp(result,ic,FALSE);
10772
10773     /* if bit then unpack */
10774     if (IS_BITFIELD(retype)) 
10775         genUnpackBits(result,left,"dptr",FPOINTER);
10776     else {
10777         size = AOP_SIZE(result);
10778         offset = 0 ;
10779
10780         while (size--) {
10781             pic16_emitcode("movx","a,@dptr");
10782             pic16_aopPut(AOP(result),"a",offset++);
10783             if (size)
10784                 pic16_emitcode("inc","dptr");
10785         }
10786     }
10787
10788     pic16_freeAsmop(result,NULL,ic,TRUE);
10789 }
10790 #if 0
10791 /*-----------------------------------------------------------------*/
10792 /* genCodePointerGet - get value from code space                  */
10793 /*-----------------------------------------------------------------*/
10794 static void genCodePointerGet (operand *left,
10795                                 operand *result, iCode *ic)
10796 {
10797     int size, offset ;
10798     sym_link *retype = getSpec(operandType(result));
10799
10800     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10801
10802     pic16_aopOp(left,ic,FALSE);
10803
10804     /* if the operand is already in dptr 
10805     then we do nothing else we move the value to dptr */
10806     if (AOP_TYPE(left) != AOP_STR) {
10807         /* if this is remateriazable */
10808         if (AOP_TYPE(left) == AOP_IMMD)
10809             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10810         else { /* we need to get it byte by byte */
10811             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10812             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10813             if (options.model == MODEL_FLAT24)
10814             {
10815                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10816             }
10817         }
10818     }
10819     /* so dptr know contains the address */
10820     pic16_freeAsmop(left,NULL,ic,TRUE);
10821     pic16_aopOp(result,ic,FALSE);
10822
10823     /* if bit then unpack */
10824     if (IS_BITFIELD(retype)) 
10825         genUnpackBits(result,left,"dptr",CPOINTER);
10826     else {
10827         size = AOP_SIZE(result);
10828         offset = 0 ;
10829
10830         while (size--) {
10831             pic16_emitcode("clr","a");
10832             pic16_emitcode("movc","a,@a+dptr");
10833             pic16_aopPut(AOP(result),"a",offset++);
10834             if (size)
10835                 pic16_emitcode("inc","dptr");
10836         }
10837     }
10838
10839     pic16_freeAsmop(result,NULL,ic,TRUE);
10840 }
10841 #endif
10842 #if 0
10843 /*-----------------------------------------------------------------*/
10844 /* genGenPointerGet - gget value from generic pointer space        */
10845 /*-----------------------------------------------------------------*/
10846 static void genGenPointerGet (operand *left,
10847                               operand *result, iCode *ic)
10848 {
10849   int size, offset, lit;
10850   sym_link *retype = getSpec(operandType(result));
10851
10852         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10853         pic16_aopOp(left,ic,FALSE);
10854         pic16_aopOp(result,ic,FALSE);
10855         size = AOP_SIZE(result);
10856
10857         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10858
10859         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10860
10861                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10862                 // load FSR0 from immediate
10863                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10864
10865 //              pic16_loadFSR0( left );
10866
10867                 offset = 0;
10868                 while(size--) {
10869                         if(size) {
10870                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10871                         } else {
10872                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10873                         }
10874                         offset++;
10875                 }
10876                 goto release;
10877
10878         }
10879         else { /* we need to get it byte by byte */
10880                 // set up FSR0 with address from left
10881                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10882                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10883
10884                 offset = 0 ;
10885
10886                 while(size--) {
10887                         if(size) {
10888                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10889                         } else {
10890                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10891                         }
10892                         offset++;
10893                 }
10894                 goto release;
10895         }
10896
10897   /* if bit then unpack */
10898         if (IS_BITFIELD(retype)) 
10899                 genUnpackBits(result,left,"BAD",GPOINTER);
10900
10901         release:
10902         pic16_freeAsmop(left,NULL,ic,TRUE);
10903         pic16_freeAsmop(result,NULL,ic,TRUE);
10904
10905 }
10906 #endif
10907
10908
10909 /*-----------------------------------------------------------------*/
10910 /* genGenPointerGet - gget value from generic pointer space        */
10911 /*-----------------------------------------------------------------*/
10912 static void genGenPointerGet (operand *left,
10913                               operand *result, iCode *ic)
10914 {
10915   int size, offset, lit;
10916   sym_link *retype = getSpec(operandType(result));
10917   char fgptrget[32];
10918
10919     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10920     pic16_aopOp(left,ic,FALSE);
10921     pic16_aopOp(result,ic,FALSE);
10922     size = AOP_SIZE(result);
10923
10924     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10925
10926     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10927
10928       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10929       // load FSR0 from immediate
10930       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10931
10932       werror(W_POSSBUG2, __FILE__, __LINE__);
10933
10934       offset = 0;
10935       while(size--) {
10936         if(size) {
10937           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10938         } else {
10939           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10940         }
10941         offset++;
10942       }
10943
10944       goto release;
10945
10946     } else { /* we need to get it byte by byte */
10947
10948       /* set up WREG:PRODL:FSR0L with address from left */
10949       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10950       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10951       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10952       
10953       switch( size ) {
10954         case 1: strcpy(fgptrget, "__gptrget1"); break;
10955         case 2: strcpy(fgptrget, "__gptrget2"); break;
10956         case 3: strcpy(fgptrget, "__gptrget3"); break;
10957         case 4: strcpy(fgptrget, "__gptrget4"); break;
10958         default:
10959           werror(W_POSSBUG2, __FILE__, __LINE__);
10960           abort();
10961       }
10962       
10963       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10964       
10965       assignResultValue(result, 1);
10966       
10967       {
10968         symbol *sym;
10969
10970           sym = newSymbol( fgptrget, 0 );
10971           strcpy(sym->rname, fgptrget);
10972           checkAddSym(&externs, sym);
10973
10974 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10975       }
10976               
10977       goto release;
10978     }
10979
10980   /* if bit then unpack */
10981     if (IS_BITFIELD(retype)) 
10982       genUnpackBits(result,left,"BAD",GPOINTER);
10983
10984 release:
10985   pic16_freeAsmop(left,NULL,ic,TRUE);
10986   pic16_freeAsmop(result,NULL,ic,TRUE);
10987 }
10988
10989 /*-----------------------------------------------------------------*/
10990 /* genConstPointerGet - get value from const generic pointer space */
10991 /*-----------------------------------------------------------------*/
10992 static void genConstPointerGet (operand *left,
10993                                 operand *result, iCode *ic)
10994 {
10995   //sym_link *retype = getSpec(operandType(result));
10996   // symbol *albl = newiTempLabel(NULL);        // patch 15
10997   // symbol *blbl = newiTempLabel(NULL);        //
10998   // PIC_OPCODE poc;                            // patch 15
10999   int size;
11000   int offset = 0;
11001
11002   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11003   pic16_aopOp(left,ic,FALSE);
11004   pic16_aopOp(result,ic,TRUE);
11005   size = AOP_SIZE(result);
11006
11007   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11008
11009   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11010 #if 0                                                                   // patch 15
11011   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11012   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11013   pic16_emitpLabel(albl->key);
11014
11015   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11016   
11017   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11018   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11019   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11020   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11021   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11022
11023   pic16_emitpLabel(blbl->key);
11024
11025   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11026 #endif                                                                  // patch 15
11027
11028
11029   // set up table pointer
11030   if( (AOP_TYPE(left) == AOP_PCODE) 
11031       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11032           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11033     {
11034       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11035       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11036       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11037       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11038       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11039       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11040     }
11041   else
11042     {
11043       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11044       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11045       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11046     }
11047
11048
11049   while(size--)
11050     {
11051       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11052       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11053       offset++;
11054     }
11055     
11056   pic16_freeAsmop(left,NULL,ic,TRUE);
11057   pic16_freeAsmop(result,NULL,ic,TRUE);
11058
11059 }
11060
11061
11062 /*-----------------------------------------------------------------*/
11063 /* genPointerGet - generate code for pointer get                   */
11064 /*-----------------------------------------------------------------*/
11065 static void genPointerGet (iCode *ic)
11066 {
11067     operand *left, *result ;
11068     sym_link *type, *etype;
11069     int p_type;
11070
11071     FENTRY;
11072     
11073     left = IC_LEFT(ic);
11074     result = IC_RESULT(ic) ;
11075
11076     /* depending on the type of pointer we need to
11077     move it to the correct pointer register */
11078     type = operandType(left);
11079     etype = getSpec(type);
11080
11081 #if 0
11082     if (IS_PTR_CONST(type))
11083 #else
11084     if (IS_CODEPTR(type))
11085 #endif
11086       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11087
11088     /* if left is of type of pointer then it is simple */
11089     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11090         p_type = DCL_TYPE(type);
11091     else {
11092         /* we have to go by the storage class */
11093         p_type = PTR_TYPE(SPEC_OCLS(etype));
11094
11095         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11096
11097         if (SPEC_OCLS(etype)->codesp ) {
11098           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11099           //p_type = CPOINTER ; 
11100         }
11101         else
11102             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11103               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11104                /*p_type = FPOINTER ;*/ 
11105             else
11106                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11107                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11108 /*                  p_type = PPOINTER; */
11109                 else
11110                     if (SPEC_OCLS(etype) == idata )
11111                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11112 /*                      p_type = IPOINTER; */
11113                     else
11114                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11115 /*                      p_type = POINTER ; */
11116     }
11117
11118     /* now that we have the pointer type we assign
11119     the pointer values */
11120     switch (p_type) {
11121
11122     case POINTER:       
11123     case IPOINTER:
11124         genNearPointerGet (left,result,ic);
11125         break;
11126
11127     case PPOINTER:
11128         genPagedPointerGet(left,result,ic);
11129         break;
11130
11131     case FPOINTER:
11132         genFarPointerGet (left,result,ic);
11133         break;
11134
11135     case CPOINTER:
11136         genConstPointerGet (left,result,ic);
11137         //pic16_emitcodePointerGet (left,result,ic);
11138         break;
11139
11140     case GPOINTER:
11141 #if 0
11142       if (IS_PTR_CONST(type))
11143         genConstPointerGet (left,result,ic);
11144       else
11145 #endif
11146         genGenPointerGet (left,result,ic);
11147       break;
11148
11149     default:
11150       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11151               "genPointerGet: illegal pointer type");
11152     
11153     }
11154
11155 }
11156
11157 /*-----------------------------------------------------------------*/
11158 /* genPackBits - generates code for packed bit storage             */
11159 /*-----------------------------------------------------------------*/
11160 static void genPackBits (sym_link    *etype , operand *result,
11161                          operand *right ,
11162                          char *rname, int p_type)
11163 {
11164   int shCnt = 0 ;
11165   int offset = 0  ;
11166   int rLen = 0 ;
11167   int blen, bstr ;   
11168   sym_link *retype;
11169   char *l ;
11170
11171         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11172         blen = SPEC_BLEN(etype);
11173         bstr = SPEC_BSTR(etype);
11174
11175         retype = getSpec(operandType(right));
11176
11177         if(AOP_TYPE(right) == AOP_LIT) {
11178                 if((blen == 1) && (bstr < 8)) {
11179                   unsigned long lit;
11180                         /* it is a single bit, so use the appropriate bit instructions */
11181
11182                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11183
11184                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11185 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11186                         if((p_type == POINTER) && (result)) {
11187                                 /* workaround to reduce the extra lfsr instruction */
11188                                 if(lit) {
11189                                         pic16_emitpcode(POC_BSF,
11190                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11191                                 } else {
11192                                         pic16_emitpcode(POC_BCF,
11193                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11194                                 }
11195                         } else {
11196                                 pic16_loadFSR0( result );
11197                                 if(lit) {
11198                                         pic16_emitpcode(POC_BSF,
11199                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11200                                 } else {
11201                                         pic16_emitpcode(POC_BCF,
11202                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11203                                 }
11204                         }
11205         
11206                   return;
11207                 }
11208
11209                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11210                 offset++;
11211         } else
11212         if(IS_BITFIELD(retype) 
11213           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11214           && (blen == 1)) {
11215           int rblen, rbstr;
11216
11217             rblen = SPEC_BLEN( retype );
11218             rbstr = SPEC_BSTR( retype );
11219             
11220
11221             if(IS_BITFIELD(etype)) {
11222               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11223               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11224             } else {
11225               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11226             }
11227             
11228             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11229             
11230             if(IS_BITFIELD(etype)) {
11231               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11232             } else {
11233               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11234             }
11235
11236             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11237             
11238             return;
11239         } else
11240           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11241
11242         /* if the bit lenth is less than or    */
11243         /* it exactly fits a byte then         */
11244         if((shCnt=SPEC_BSTR(etype))
11245                 || SPEC_BLEN(etype) <= 8 )  {
11246
11247                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11248
11249                 /* shift left acc */
11250                 AccLsh(shCnt);
11251
11252                 /* using PRODL as a temporary register here */
11253                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11254
11255                 switch (p_type) {
11256                         case FPOINTER:
11257                         case POINTER:
11258                                 pic16_loadFSR0( result );
11259                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11260 //                              pic16_emitcode ("mov","b,a");
11261 //                              pic16_emitcode("mov","a,@%s",rname);
11262                                 break;
11263
11264                         case GPOINTER:
11265                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11266                                 break;
11267
11268                 }
11269 #if 1
11270                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11271                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11272                                         (unsigned char)(0xff >> (8-bstr))) ));
11273                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11274                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11275 #endif
11276
11277           return;
11278         }
11279
11280
11281         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11282         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11283         exit(-1);
11284
11285
11286     /* if we r done */
11287     if ( SPEC_BLEN(etype) <= 8 )
11288         return ;
11289
11290     pic16_emitcode("inc","%s",rname);
11291     rLen = SPEC_BLEN(etype) ;     
11292
11293
11294
11295     /* now generate for lengths greater than one byte */
11296     while (1) {
11297
11298         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11299
11300         rLen -= 8 ;
11301         if (rLen <= 0 )
11302             break ;
11303
11304         switch (p_type) {
11305             case POINTER:
11306                 if (*l == '@') {
11307                     MOVA(l);
11308                     pic16_emitcode("mov","@%s,a",rname);
11309                 } else
11310                     pic16_emitcode("mov","@%s,%s",rname,l);
11311                 break;
11312
11313             case FPOINTER:
11314                 MOVA(l);
11315                 pic16_emitcode("movx","@dptr,a");
11316                 break;
11317
11318             case GPOINTER:
11319                 MOVA(l);
11320                 DEBUGpic16_emitcode(";lcall","__gptrput");
11321                 break;  
11322         }   
11323         pic16_emitcode ("inc","%s",rname);
11324     }
11325
11326     MOVA(l);
11327
11328     /* last last was not complete */
11329     if (rLen)   {
11330         /* save the byte & read byte */
11331         switch (p_type) {
11332             case POINTER:
11333                 pic16_emitcode ("mov","b,a");
11334                 pic16_emitcode("mov","a,@%s",rname);
11335                 break;
11336
11337             case FPOINTER:
11338                 pic16_emitcode ("mov","b,a");
11339                 pic16_emitcode("movx","a,@dptr");
11340                 break;
11341
11342             case GPOINTER:
11343                 pic16_emitcode ("push","b");
11344                 pic16_emitcode ("push","acc");
11345                 pic16_emitcode ("lcall","__gptrget");
11346                 pic16_emitcode ("pop","b");
11347                 break;
11348         }
11349
11350         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11351         pic16_emitcode ("orl","a,b");
11352     }
11353
11354     if (p_type == GPOINTER)
11355         pic16_emitcode("pop","b");
11356
11357     switch (p_type) {
11358
11359     case POINTER:
11360         pic16_emitcode("mov","@%s,a",rname);
11361         break;
11362         
11363     case FPOINTER:
11364         pic16_emitcode("movx","@dptr,a");
11365         break;
11366         
11367     case GPOINTER:
11368         DEBUGpic16_emitcode(";lcall","__gptrput");
11369         break;                  
11370     }
11371 }
11372 /*-----------------------------------------------------------------*/
11373 /* genDataPointerSet - remat pointer to data space                 */
11374 /*-----------------------------------------------------------------*/
11375 static void genDataPointerSet(operand *right,
11376                               operand *result,
11377                               iCode *ic)
11378 {
11379     int size, offset = 0, resoffset=0 ;
11380
11381     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11382     pic16_aopOp(right,ic,FALSE);
11383
11384     size = AOP_SIZE(right);
11385
11386 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11387
11388 #if 0
11389     if ( AOP_TYPE(result) == AOP_PCODE) {
11390       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11391               AOP(result)->aopu.pcop->name,
11392                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11393               PCOR(AOP(result)->aopu.pcop)->instance:
11394               PCOI(AOP(result)->aopu.pcop)->offset);
11395     }
11396 #endif
11397
11398         if(AOP(result)->aopu.pcop->type == PO_DIR)
11399                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11400
11401         while (size--) {
11402                 if (AOP_TYPE(right) == AOP_LIT) {
11403                   unsigned int lit;
11404
11405                     if(!IS_FLOAT(operandType( right )))
11406                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11407                     else {
11408                       union {
11409                         unsigned long lit_int;
11410                         float lit_float;
11411                       } info;
11412         
11413                         /* take care if literal is a float */
11414                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11415                         lit = info.lit_int;
11416                     }
11417
11418                     lit = lit >> (8*offset);
11419                     if(lit&0xff) {
11420                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11421                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11422                     } else {
11423                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11424                     }
11425                 } else {
11426                   pic16_mov2w(AOP(right), offset);
11427                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11428                 }
11429                 offset++;
11430                 resoffset++;
11431         }
11432
11433     pic16_freeAsmop(right,NULL,ic,TRUE);
11434 }
11435
11436
11437
11438 /*-----------------------------------------------------------------*/
11439 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11440 /*-----------------------------------------------------------------*/
11441 static void genNearPointerSet (operand *right,
11442                                operand *result, 
11443                                iCode *ic)
11444 {
11445   asmop *aop = NULL;
11446   char *l;
11447   sym_link *retype;
11448   sym_link *ptype = operandType(result);
11449   sym_link *resetype;
11450     
11451         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11452         retype= getSpec(operandType(right));
11453         resetype = getSpec(operandType(result));
11454   
11455         pic16_aopOp(result,ic,FALSE);
11456     
11457         /* if the result is rematerializable &
11458          * in data space & not a bit variable */
11459         
11460         /* and result is not a bit variable */
11461         if (AOP_TYPE(result) == AOP_PCODE
11462 //              && AOP_TYPE(result) == AOP_IMMD
11463                 && DCL_TYPE(ptype) == POINTER
11464                 && !IS_BITFIELD(retype)
11465                 && !IS_BITFIELD(resetype)) {
11466
11467                 genDataPointerSet (right,result,ic);
11468                 pic16_freeAsmop(result,NULL,ic,TRUE);
11469           return;
11470         }
11471
11472         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11473         pic16_aopOp(right,ic,FALSE);
11474         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11475
11476         /* if the value is already in a pointer register
11477          * then don't need anything more */
11478         if (!AOP_INPREG(AOP(result))) {
11479                 /* otherwise get a free pointer register */
11480                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11481
11482 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11483 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11484 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11485                 if(is_LitAOp( AOP(result) ))
11486                 {
11487                   if(!IS_BITFIELD(resetype))
11488                         pic16_loadFSR0( result );  // patch 10
11489                 } else {
11490                   if(!IS_BITFIELD(resetype)) {
11491                         // set up FSR0 with address of result
11492                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11493                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11494                   }
11495                 }
11496
11497         }
11498 //      else
11499 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11500
11501         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11502
11503 //      pic16_loadFSR0( result );
11504
11505         /* if bitfield then unpack the bits */
11506         if (IS_BITFIELD(resetype)) {
11507                 genPackBits (resetype, result, right, NULL, POINTER);
11508         } else {
11509                 /* we have can just get the values */
11510           int size = AOP_SIZE(right);
11511           int offset = 0 ;    
11512
11513                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11514                 while (size--) {
11515                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11516                         if (*l == '@' ) {
11517                                 //MOVA(l);
11518                                 //pic16_emitcode("mov","@%s,a",rname);
11519                                 pic16_emitcode("movf","indf0,w ;1");
11520                         } else {
11521
11522                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11523                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11524                                         if (size) {                                                                     // 
11525                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11526                                         } else {                                                                        // 
11527                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11528                                         }                                                                               // 
11529                                 } else { // no literal                                                                  // 
11530                                         if(size) {                                                                      // 
11531                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11532                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11533                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11534                                         } else {                                                                        // 
11535                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11536                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11537                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11538                                         }                                                                               //
11539                                 }                                                                                       // patch 10
11540                         }
11541                         offset++;
11542                 }
11543         }
11544
11545         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11546         /* now some housekeeping stuff */
11547         if (aop) {
11548                 /* we had to allocate for this iCode */
11549                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11550         } else { 
11551                 /* we did not allocate which means left
11552                  * already in a pointer register, then
11553                  * if size > 0 && this could be used again
11554                  * we have to point it back to where it 
11555                  * belongs */
11556                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11557                 if (AOP_SIZE(right) > 1
11558                         && !OP_SYMBOL(result)->remat
11559                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11560                                 || ic->depth )) {
11561
11562                   int size = AOP_SIZE(right) - 1;
11563
11564                         while (size--)
11565                                 pic16_emitcode("decf","fsr0,f");
11566                         //pic16_emitcode("dec","%s",rname);
11567                 }
11568         }
11569
11570         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11571         /* done */
11572 //release:
11573         pic16_freeAsmop(right,NULL,ic,TRUE);
11574         pic16_freeAsmop(result,NULL,ic,TRUE);
11575 }
11576
11577 /*-----------------------------------------------------------------*/
11578 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11579 /*-----------------------------------------------------------------*/
11580 static void genPagedPointerSet (operand *right,
11581                                operand *result, 
11582                                iCode *ic)
11583 {
11584     asmop *aop = NULL;
11585     regs *preg = NULL ;
11586     char *rname , *l;
11587     sym_link *retype;
11588        
11589     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11590
11591     retype= getSpec(operandType(right));
11592     
11593     pic16_aopOp(result,ic,FALSE);
11594     
11595     /* if the value is already in a pointer register
11596        then don't need anything more */
11597     if (!AOP_INPREG(AOP(result))) {
11598         /* otherwise get a free pointer register */
11599         aop = newAsmop(0);
11600         preg = getFreePtr(ic,&aop,FALSE);
11601         pic16_emitcode("mov","%s,%s",
11602                 preg->name,
11603                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11604         rname = preg->name ;
11605     } else
11606         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11607     
11608     pic16_freeAsmop(result,NULL,ic,TRUE);
11609     pic16_aopOp (right,ic,FALSE);
11610
11611     /* if bitfield then unpack the bits */
11612     if (IS_BITFIELD(retype)) 
11613         genPackBits (retype,result,right,rname,PPOINTER);
11614     else {
11615         /* we have can just get the values */
11616         int size = AOP_SIZE(right);
11617         int offset = 0 ;        
11618         
11619         while (size--) {
11620             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11621             
11622             MOVA(l);
11623             pic16_emitcode("movx","@%s,a",rname);
11624
11625             if (size)
11626                 pic16_emitcode("inc","%s",rname);
11627
11628             offset++;
11629         }
11630     }
11631     
11632     /* now some housekeeping stuff */
11633     if (aop) {
11634         /* we had to allocate for this iCode */
11635         pic16_freeAsmop(NULL,aop,ic,TRUE);
11636     } else { 
11637         /* we did not allocate which means left
11638            already in a pointer register, then
11639            if size > 0 && this could be used again
11640            we have to point it back to where it 
11641            belongs */
11642         if (AOP_SIZE(right) > 1 &&
11643             !OP_SYMBOL(result)->remat &&
11644             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11645               ic->depth )) {
11646             int size = AOP_SIZE(right) - 1;
11647             while (size--)
11648                 pic16_emitcode("dec","%s",rname);
11649         }
11650     }
11651
11652     /* done */
11653     pic16_freeAsmop(right,NULL,ic,TRUE);
11654     
11655         
11656 }
11657
11658 /*-----------------------------------------------------------------*/
11659 /* genFarPointerSet - set value from far space                     */
11660 /*-----------------------------------------------------------------*/
11661 static void genFarPointerSet (operand *right,
11662                               operand *result, iCode *ic)
11663 {
11664     int size, offset ;
11665     sym_link *retype = getSpec(operandType(right));
11666
11667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11668     pic16_aopOp(result,ic,FALSE);
11669
11670     /* if the operand is already in dptr 
11671     then we do nothing else we move the value to dptr */
11672     if (AOP_TYPE(result) != AOP_STR) {
11673         /* if this is remateriazable */
11674         if (AOP_TYPE(result) == AOP_IMMD)
11675             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11676         else { /* we need to get it byte by byte */
11677             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11678             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11679             if (options.model == MODEL_FLAT24)
11680             {
11681                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11682             }
11683         }
11684     }
11685     /* so dptr know contains the address */
11686     pic16_freeAsmop(result,NULL,ic,TRUE);
11687     pic16_aopOp(right,ic,FALSE);
11688
11689     /* if bit then unpack */
11690     if (IS_BITFIELD(retype)) 
11691         genPackBits(retype,result,right,"dptr",FPOINTER);
11692     else {
11693         size = AOP_SIZE(right);
11694         offset = 0 ;
11695
11696         while (size--) {
11697             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11698             MOVA(l);
11699             pic16_emitcode("movx","@dptr,a");
11700             if (size)
11701                 pic16_emitcode("inc","dptr");
11702         }
11703     }
11704
11705     pic16_freeAsmop(right,NULL,ic,TRUE);
11706 }
11707
11708 /*-----------------------------------------------------------------*/
11709 /* genGenPointerSet - set value from generic pointer space         */
11710 /*-----------------------------------------------------------------*/
11711 #if 0
11712 static void genGenPointerSet (operand *right,
11713                               operand *result, iCode *ic)
11714 {
11715         int i, size, offset, lit;
11716         sym_link *retype = getSpec(operandType(right));
11717
11718         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11719
11720         pic16_aopOp(result,ic,FALSE);
11721         pic16_aopOp(right,ic,FALSE);
11722         size = AOP_SIZE(right);
11723         offset = 0;
11724
11725         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11726
11727         /* if the operand is already in dptr 
11728                 then we do nothing else we move the value to dptr */
11729         if (AOP_TYPE(result) != AOP_STR) {
11730                 /* if this is remateriazable */
11731                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11732                 // WARNING: anythig until "else" is untested!
11733                 if (AOP_TYPE(result) == AOP_IMMD) {
11734                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11735                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11736                         // load FSR0 from immediate
11737                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11738                         offset = 0;
11739                         while(size--) {
11740                                 if(size) {
11741                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11742                                 } else {
11743                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11744                                 }
11745                                 offset++;
11746                         }
11747                         goto release;
11748                 }
11749                 else { /* we need to get it byte by byte */
11750                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11751                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11752
11753                         // set up FSR0 with address of result
11754                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11755                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11756
11757                         /* hack hack! see if this the FSR. If so don't load W */
11758                         if(AOP_TYPE(right) != AOP_ACC) {
11759
11760                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11761
11762                                 if(AOP_TYPE(right) == AOP_LIT)
11763                                 {
11764                                         // copy literal
11765                                         // note: pic16_popGet handles sign extension
11766                                         for(i=0;i<size;i++) {
11767                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11768                                                 if(i < size-1)
11769                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11770                                                 else
11771                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11772                                         }
11773                                 } else {
11774                                         // copy regs
11775
11776                                         for(i=0;i<size;i++) {
11777                                                 if(i < size-1)
11778                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11779                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11780                                                 else
11781                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11782                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11783                                         }
11784                                 }
11785                                 goto release;
11786                         } 
11787                         // right = ACC
11788                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11789                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11790                         goto release;
11791         } // if (AOP_TYPE(result) != AOP_IMMD)
11792
11793         } // if (AOP_TYPE(result) != AOP_STR)
11794         /* so dptr know contains the address */
11795
11796
11797         /* if bit then unpack */
11798         if (IS_BITFIELD(retype)) 
11799                 genPackBits(retype,result,right,"dptr",GPOINTER);
11800         else {
11801                 size = AOP_SIZE(right);
11802                 offset = 0 ;
11803
11804                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11805
11806                 // set up FSR0 with address of result
11807                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11808                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11809         
11810                 while (size--) {
11811                         if (AOP_TYPE(right) == AOP_LIT) {
11812                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11813                                 if (size) {
11814                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11815                                 } else {
11816                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11817                                 }
11818                         } else { // no literal
11819                                 if(size) {
11820                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11821                                 } else {
11822                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11823                                 }
11824                         }
11825                         offset++;
11826                 }
11827         }
11828
11829         release:
11830         pic16_freeAsmop(right,NULL,ic,TRUE);
11831         pic16_freeAsmop(result,NULL,ic,TRUE);
11832 }
11833 #endif
11834
11835 static void genGenPointerSet (operand *right,
11836                               operand *result, iCode *ic)
11837 {
11838   int size;
11839   sym_link *retype = getSpec(operandType(right));
11840   char fgptrput[32];
11841
11842     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11843
11844     pic16_aopOp(result,ic,FALSE);
11845     pic16_aopOp(right,ic,FALSE);
11846     size = AOP_SIZE(right);
11847
11848     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11849
11850
11851     /* if bit then unpack */
11852     if (IS_BITFIELD(retype)) {
11853 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11854       genPackBits(retype,result,right,"dptr",GPOINTER);
11855       goto release;
11856     }
11857
11858     size = AOP_SIZE(right);
11859
11860     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11861
11862
11863
11864     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11865
11866     /* value of right+0 is placed on stack, which will be retrieved
11867      * by the support function this restoring the stack. The important
11868      * thing is that there is no need to manually restore stack pointer
11869      * here */
11870     pushaop(AOP(right), 0);
11871 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11872     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11873     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11874     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11875     
11876     /* load address to write to in WREG:FSR0H:FSR0L */
11877     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11878                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11879     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11880                                 pic16_popCopyReg(&pic16_pc_prodl)));
11881     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11882     
11883
11884     /* put code here */
11885     switch (size) {
11886       case 1: strcpy(fgptrput, "__gptrput1"); break;
11887       case 2: strcpy(fgptrput, "__gptrput2"); break;
11888       case 3: strcpy(fgptrput, "__gptrput3"); break;
11889       case 4: strcpy(fgptrput, "__gptrput4"); break;
11890       default:
11891         werror(W_POSSBUG2, __FILE__, __LINE__);
11892         abort();
11893     }
11894     
11895     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11896     
11897     {
11898       symbol *sym;
11899                   
11900         sym = newSymbol( fgptrput, 0 );
11901         strcpy(sym->rname, fgptrput);
11902         checkAddSym(&externs, sym);
11903     }
11904
11905 release:
11906     pic16_freeAsmop(right,NULL,ic,TRUE);
11907     pic16_freeAsmop(result,NULL,ic,TRUE);
11908 }
11909
11910 /*-----------------------------------------------------------------*/
11911 /* genPointerSet - stores the value into a pointer location        */
11912 /*-----------------------------------------------------------------*/
11913 static void genPointerSet (iCode *ic)
11914 {    
11915   operand *right, *result ;
11916   sym_link *type, *etype;
11917   int p_type;
11918
11919     FENTRY;
11920
11921     right = IC_RIGHT(ic);
11922     result = IC_RESULT(ic) ;
11923
11924     /* depending on the type of pointer we need to
11925     move it to the correct pointer register */
11926     type = operandType(result);
11927     etype = getSpec(type);
11928     /* if left is of type of pointer then it is simple */
11929     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11930         p_type = DCL_TYPE(type);
11931     }
11932     else {
11933         /* we have to go by the storage class */
11934         p_type = PTR_TYPE(SPEC_OCLS(etype));
11935
11936 /*      if (SPEC_OCLS(etype)->codesp ) { */
11937 /*          p_type = CPOINTER ;  */
11938 /*      } */
11939 /*      else */
11940 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11941 /*              p_type = FPOINTER ; */
11942 /*          else */
11943 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11944 /*                  p_type = PPOINTER ; */
11945 /*              else */
11946 /*                  if (SPEC_OCLS(etype) == idata ) */
11947 /*                      p_type = IPOINTER ; */
11948 /*                  else */
11949 /*                      p_type = POINTER ; */
11950     }
11951
11952     /* now that we have the pointer type we assign
11953     the pointer values */
11954     switch (p_type) {
11955
11956     case POINTER:
11957     case IPOINTER:
11958         genNearPointerSet (right,result,ic);
11959         break;
11960
11961     case PPOINTER:
11962         genPagedPointerSet (right,result,ic);
11963         break;
11964
11965     case FPOINTER:
11966         genFarPointerSet (right,result,ic);
11967         break;
11968
11969     case GPOINTER:
11970         genGenPointerSet (right,result,ic);
11971         break;
11972
11973     default:
11974       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11975               "genPointerSet: illegal pointer type");
11976     }
11977 }
11978
11979 /*-----------------------------------------------------------------*/
11980 /* genIfx - generate code for Ifx statement                        */
11981 /*-----------------------------------------------------------------*/
11982 static void genIfx (iCode *ic, iCode *popIc)
11983 {
11984   operand *cond = IC_COND(ic);
11985   int isbit =0;
11986
11987     FENTRY;
11988
11989     pic16_aopOp(cond,ic,FALSE);
11990
11991     /* get the value into acc */
11992     if (AOP_TYPE(cond) != AOP_CRY)
11993       pic16_toBoolean(cond);
11994     else
11995       isbit = 1;
11996     /* the result is now in the accumulator */
11997     pic16_freeAsmop(cond,NULL,ic,TRUE);
11998
11999     /* if there was something to be popped then do it */
12000     if (popIc)
12001       genIpop(popIc);
12002
12003     /* if the condition is  a bit variable */
12004     if (isbit && IS_ITEMP(cond) && 
12005         SPIL_LOC(cond)) {
12006       genIfxJump(ic,SPIL_LOC(cond)->rname);
12007       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12008     } else {
12009       if (isbit && !IS_ITEMP(cond))
12010         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12011         else
12012         genIfxJump(ic,"a");
12013     }
12014     ic->generated = 1;
12015 }
12016
12017 /*-----------------------------------------------------------------*/
12018 /* genAddrOf - generates code for address of                       */
12019 /*-----------------------------------------------------------------*/
12020 static void genAddrOf (iCode *ic)
12021 {
12022   operand *result, *left;
12023   int size;
12024   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12025   pCodeOp *pcop0, *pcop1, *pcop2;
12026
12027     FENTRY;
12028
12029     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12030
12031     sym = OP_SYMBOL( IC_LEFT(ic) );
12032     
12033     if(sym->onStack) {
12034       /* get address of symbol on stack */
12035       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12036 #if 0
12037       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12038                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12039 #endif
12040
12041       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12042                       pic16_popCopyReg(&pic16_pc_fsr2l),
12043                       pic16_popGet(AOP(result), 0)));
12044       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12045                       pic16_popCopyReg(&pic16_pc_fsr2h),
12046                       pic16_popGet(AOP(result), 1)));
12047      
12048       // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
12049       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( - (OP_SYMBOL( IC_LEFT(ic))->stack + 1 ) /*+ _G.stack_lat*/));
12050       pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result), 0));
12051       emitSKPC;
12052       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result), 1));
12053
12054       goto release;
12055     }
12056         
12057 //      if(pic16_debug_verbose) {
12058 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12059 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12060 //      }
12061         
12062     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12063     size = AOP_SIZE(IC_RESULT(ic));
12064
12065
12066     /* Assume that what we want the address of is in data space
12067      * since there is no stack on the PIC, yet! -- VR */
12068   
12069     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12070     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12071     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12072         
12073     if (size == 3) {
12074       pic16_emitpcode(POC_MOVLW, pcop0);
12075       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12076       pic16_emitpcode(POC_MOVLW, pcop1);
12077       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12078       pic16_emitpcode(POC_MOVLW, pcop2);
12079       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12080     } else
12081     if (size == 2) {
12082       pic16_emitpcode(POC_MOVLW, pcop0);
12083       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12084       pic16_emitpcode(POC_MOVLW, pcop1);
12085     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12086     } else {
12087       pic16_emitpcode(POC_MOVLW, pcop0);
12088       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12089     }
12090
12091     pic16_freeAsmop(left, NULL, ic, FALSE);
12092 release:
12093     pic16_freeAsmop(result,NULL,ic,TRUE);
12094 }
12095
12096
12097 #if 0
12098 /*-----------------------------------------------------------------*/
12099 /* genFarFarAssign - assignment when both are in far space         */
12100 /*-----------------------------------------------------------------*/
12101 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12102 {
12103     int size = AOP_SIZE(right);
12104     int offset = 0;
12105     char *l ;
12106     /* first push the right side on to the stack */
12107     while (size--) {
12108         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12109         MOVA(l);
12110         pic16_emitcode ("push","acc");
12111     }
12112     
12113     pic16_freeAsmop(right,NULL,ic,FALSE);
12114     /* now assign DPTR to result */
12115     pic16_aopOp(result,ic,FALSE);
12116     size = AOP_SIZE(result);
12117     while (size--) {
12118         pic16_emitcode ("pop","acc");
12119         pic16_aopPut(AOP(result),"a",--offset);
12120     }
12121     pic16_freeAsmop(result,NULL,ic,FALSE);
12122         
12123 }
12124 #endif
12125
12126 /*-----------------------------------------------------------------*/
12127 /* genAssign - generate code for assignment                        */
12128 /*-----------------------------------------------------------------*/
12129 static void genAssign (iCode *ic)
12130 {
12131   operand *result, *right;
12132   int size, offset,know_W;
12133   unsigned long lit = 0L;
12134
12135   result = IC_RESULT(ic);
12136   right  = IC_RIGHT(ic) ;
12137
12138   FENTRY;
12139   
12140   /* if they are the same */
12141   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12142     return ;
12143
12144   /* reversed order operands are aopOp'ed so that result operand
12145    * is effective in case right is a stack symbol. This maneauver
12146    * allows to use the _G.resDirect flag later */
12147   pic16_aopOp(result,ic,TRUE);
12148   pic16_aopOp(right,ic,FALSE);
12149
12150   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12151
12152   /* if they are the same registers */
12153   if (pic16_sameRegs(AOP(right),AOP(result)))
12154     goto release;
12155
12156   /* if the result is a bit */
12157   if (AOP_TYPE(result) == AOP_CRY) {
12158     /* if the right size is a literal then
12159        we know what the value is */
12160     if (AOP_TYPE(right) == AOP_LIT) {
12161           
12162       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12163                   pic16_popGet(AOP(result),0));
12164
12165       if (((int) operandLitValue(right))) 
12166         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12167                        AOP(result)->aopu.aop_dir,
12168                        AOP(result)->aopu.aop_dir);
12169       else
12170         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12171                        AOP(result)->aopu.aop_dir,
12172                        AOP(result)->aopu.aop_dir);
12173       goto release;
12174     }
12175
12176     /* the right is also a bit variable */
12177     if (AOP_TYPE(right) == AOP_CRY) {
12178       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12179       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12180       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12181
12182       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12183                      AOP(result)->aopu.aop_dir,
12184                      AOP(result)->aopu.aop_dir);
12185       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12186                      AOP(right)->aopu.aop_dir,
12187                      AOP(right)->aopu.aop_dir);
12188       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12189                      AOP(result)->aopu.aop_dir,
12190                      AOP(result)->aopu.aop_dir);
12191       goto release ;
12192     }
12193
12194     /* we need to or */
12195     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12196     pic16_toBoolean(right);
12197     emitSKPZ;
12198     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12199     //pic16_aopPut(AOP(result),"a",0);
12200     goto release ;
12201   }
12202
12203   /* bit variables done */
12204   /* general case */
12205   size = AOP_SIZE(result);
12206   offset = 0 ;
12207
12208   if(AOP_TYPE(right) == AOP_LIT) {
12209         if(!IS_FLOAT(operandType( right )))
12210                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12211         else {
12212            union {
12213               unsigned long lit_int;
12214               float lit_float;
12215             } info;
12216         
12217                 /* take care if literal is a float */
12218                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12219                 lit = info.lit_int;
12220         }
12221   }
12222
12223 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12224 //                      sizeof(unsigned long int), sizeof(float));
12225
12226
12227   if (AOP_TYPE(right) == AOP_REG) {
12228     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12229     while (size--) {
12230       
12231       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12232     } // while
12233     goto release;
12234   }
12235
12236   if(AOP_TYPE(right) != AOP_LIT
12237         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12238         && !IS_FUNC(OP_SYM_TYPE(right))
12239         ) {
12240         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12241         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12242
12243         // set up table pointer
12244         if(is_LitOp(right)) {
12245 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12246                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12247                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12248                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12249                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12250                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12251                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12252         } else {
12253 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12254                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12255                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12256                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12257                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12258                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12259                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12260         }
12261
12262         size = min(AOP_SIZE(right), AOP_SIZE(result));
12263         while(size--) {
12264                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12265                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12266                         pic16_popGet(AOP(result),offset)));
12267                 offset++;
12268         }
12269
12270         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12271                 size = AOP_SIZE(result) - AOP_SIZE(right);
12272                 while(size--) {
12273                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12274                         offset++;
12275                 }
12276         }
12277         goto release;
12278   }
12279
12280
12281
12282 #if 0
12283 /* VR - What is this?! */
12284   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12286     if(aopIdx(AOP(result),0) == 4) {
12287
12288       /* this is a workaround to save value of right into wreg too,
12289        * value of wreg is going to be used later */
12290       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12291       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12292       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12293       goto release;
12294     } else
12295 //      assert(0);
12296       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12297   }
12298 #endif
12299
12300   know_W=-1;
12301   while (size--) {
12302   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12303     if(AOP_TYPE(right) == AOP_LIT) {
12304       if(lit&0xff) {
12305         if(know_W != (lit&0xff))
12306           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12307         know_W = lit&0xff;
12308         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12309       } else
12310         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12311
12312       lit >>= 8;
12313
12314     } else if (AOP_TYPE(right) == AOP_CRY) {
12315       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12316       if(offset == 0) {
12317         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12318         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12319         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12320       }
12321     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12322         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12323         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12324     } else {
12325       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12326
12327       if(!_G.resDirect)         /* use this aopForSym feature */
12328         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12329     }
12330             
12331     offset++;
12332   }
12333   
12334  release:
12335   pic16_freeAsmop (right,NULL,ic,FALSE);
12336   pic16_freeAsmop (result,NULL,ic,TRUE);
12337 }   
12338
12339 /*-----------------------------------------------------------------*/
12340 /* genJumpTab - generates code for jump table                       */
12341 /*-----------------------------------------------------------------*/
12342 static void genJumpTab (iCode *ic)
12343 {
12344   symbol *jtab;
12345   char *l;
12346   pCodeOp *jt_offs;
12347   pCodeOp *jt_offs_hi;
12348   pCodeOp *jt_label;
12349
12350     FENTRY;
12351
12352     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12353     /* get the condition into accumulator */
12354     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12355     MOVA(l);
12356     /* multiply by three */
12357     pic16_emitcode("add","a,acc");
12358     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12359
12360     jtab = newiTempLabel(NULL);
12361     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12362     pic16_emitcode("jmp","@a+dptr");
12363     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12364
12365 #if 0
12366     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12367     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12368     emitSKPNC;
12369     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12370     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12371     pic16_emitpLabel(jtab->key);
12372
12373 #else
12374
12375     jt_offs = pic16_popGetTempReg(0);
12376     jt_offs_hi = pic16_popGetTempReg(1);
12377     jt_label = pic16_popGetLabel (jtab->key);
12378     //fprintf (stderr, "Creating jump table...\n");
12379
12380     // calculate offset into jump table (idx * sizeof (GOTO))
12381     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12382     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12383     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12384     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12385     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12386     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12387     pic16_emitpcode(POC_MOVWF , jt_offs);
12388
12389     // prepare PCLATx (set to first entry in jump table)
12390     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12391     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12392     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12393     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12394     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12395
12396     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12397     pic16_emitpcode(POC_ADDWF , jt_offs);
12398     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12399     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12400     emitSKPNC;
12401     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12402
12403     // release temporaries and prepare jump into table (new PCL --> WREG)
12404     pic16_emitpcode(POC_MOVFW , jt_offs);
12405     pic16_popReleaseTempReg (jt_offs_hi, 1);
12406     pic16_popReleaseTempReg (jt_offs, 0);
12407
12408     // jump into the table
12409     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12410
12411     pic16_emitpLabelFORCE(jtab->key);
12412
12413 #endif
12414     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12415
12416     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12417     /* now generate the jump labels */
12418     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12419          jtab = setNextItem(IC_JTLABELS(ic))) {
12420 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12421         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12422         
12423     }
12424     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12425
12426 }
12427
12428 /*-----------------------------------------------------------------*/
12429 /* genMixedOperation - gen code for operators between mixed types  */
12430 /*-----------------------------------------------------------------*/
12431 /*
12432   TSD - Written for the PIC port - but this unfortunately is buggy.
12433   This routine is good in that it is able to efficiently promote 
12434   types to different (larger) sizes. Unfortunately, the temporary
12435   variables that are optimized out by this routine are sometimes
12436   used in other places. So until I know how to really parse the 
12437   iCode tree, I'm going to not be using this routine :(.
12438 */
12439 static int genMixedOperation (iCode *ic)
12440 {
12441 #if 0
12442   operand *result = IC_RESULT(ic);
12443   sym_link *ctype = operandType(IC_LEFT(ic));
12444   operand *right = IC_RIGHT(ic);
12445   int ret = 0;
12446   int big,small;
12447   int offset;
12448
12449   iCode *nextic;
12450   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12451
12452   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12453
12454   nextic = ic->next;
12455   if(!nextic)
12456     return 0;
12457
12458   nextright = IC_RIGHT(nextic);
12459   nextleft  = IC_LEFT(nextic);
12460   nextresult = IC_RESULT(nextic);
12461
12462   pic16_aopOp(right,ic,FALSE);
12463   pic16_aopOp(result,ic,FALSE);
12464   pic16_aopOp(nextright,  nextic, FALSE);
12465   pic16_aopOp(nextleft,   nextic, FALSE);
12466   pic16_aopOp(nextresult, nextic, FALSE);
12467
12468   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12469
12470     operand *t = right;
12471     right = nextright;
12472     nextright = t; 
12473
12474     pic16_emitcode(";remove right +","");
12475
12476   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12477 /*
12478     operand *t = right;
12479     right = nextleft;
12480     nextleft = t; 
12481 */
12482     pic16_emitcode(";remove left +","");
12483   } else
12484     return 0;
12485
12486   big = AOP_SIZE(nextleft);
12487   small = AOP_SIZE(nextright);
12488
12489   switch(nextic->op) {
12490
12491   case '+':
12492     pic16_emitcode(";optimize a +","");
12493     /* if unsigned or not an integral type */
12494     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12495       pic16_emitcode(";add a bit to something","");
12496     } else {
12497
12498       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12499
12500       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12501         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12502         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12503       } else
12504         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12505
12506       offset = 0;
12507       while(--big) {
12508
12509         offset++;
12510
12511         if(--small) {
12512           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12513             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12514             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12515           }
12516
12517           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12518           emitSKPNC;
12519           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12520                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12521                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12522           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12523           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12524
12525         } else {
12526           pic16_emitcode("rlf","known_zero,w");
12527
12528           /*
12529             if right is signed
12530               btfsc  right,7
12531                addlw ff
12532           */
12533           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12534             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12535             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12536           } else {
12537             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12538           }
12539         }
12540       }
12541       ret = 1;
12542     }
12543   }
12544   ret = 1;
12545
12546 release:
12547   pic16_freeAsmop(right,NULL,ic,TRUE);
12548   pic16_freeAsmop(result,NULL,ic,TRUE);
12549   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12550   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12551   if(ret)
12552     nextic->generated = 1;
12553
12554   return ret;
12555 #else
12556   return 0;
12557 #endif
12558 }
12559 /*-----------------------------------------------------------------*/
12560 /* genCast - gen code for casting                                  */
12561 /*-----------------------------------------------------------------*/
12562 static void genCast (iCode *ic)
12563 {
12564   operand *result = IC_RESULT(ic);
12565   sym_link *ctype = operandType(IC_LEFT(ic));
12566   sym_link *rtype = operandType(IC_RIGHT(ic));
12567   sym_link *restype = operandType(IC_RESULT(ic));
12568   operand *right = IC_RIGHT(ic);
12569   int size, offset ;
12570
12571
12572     FENTRY;
12573
12574         /* if they are equivalent then do nothing */
12575 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12576 //              return ;
12577
12578         pic16_aopOp(right,ic,FALSE) ;
12579         pic16_aopOp(result,ic,FALSE);
12580
12581         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12582
12583
12584         /* if the result is a bit */
12585         if (AOP_TYPE(result) == AOP_CRY) {
12586         
12587                 /* if the right size is a literal then
12588                  * we know what the value is */
12589                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12590
12591                 if (AOP_TYPE(right) == AOP_LIT) {
12592                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12593                                 pic16_popGet(AOP(result),0));
12594
12595                         if (((int) operandLitValue(right))) 
12596                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12597                                         AOP(result)->aopu.aop_dir,
12598                                         AOP(result)->aopu.aop_dir);
12599                         else
12600                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12601                                         AOP(result)->aopu.aop_dir,
12602                                         AOP(result)->aopu.aop_dir);
12603                         goto release;
12604                 }
12605
12606                 /* the right is also a bit variable */
12607                 if (AOP_TYPE(right) == AOP_CRY) {
12608                         emitCLRC;
12609                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12610
12611                         pic16_emitcode("clrc","");
12612                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12613                                 AOP(right)->aopu.aop_dir,
12614                                 AOP(right)->aopu.aop_dir);
12615                         pic16_aopPut(AOP(result),"c",0);
12616                         goto release ;
12617                 }
12618
12619                 /* we need to or */
12620                 if (AOP_TYPE(right) == AOP_REG) {
12621                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12622                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12623                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12624                 }
12625                 pic16_toBoolean(right);
12626                 pic16_aopPut(AOP(result),"a",0);
12627                 goto release ;
12628         }
12629
12630         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12631           int offset = 1;
12632
12633                 size = AOP_SIZE(result);
12634
12635                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12636
12637                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12638                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12639                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12640
12641                 while (size--)
12642                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12643
12644                 goto release;
12645         }
12646
12647         if(IS_BITFIELD(getSpec(restype))
12648           && IS_BITFIELD(getSpec(rtype))) {
12649           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12650         }
12651
12652         /* if they are the same size : or less */
12653         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12654
12655                 /* if they are in the same place */
12656                 if (pic16_sameRegs(AOP(right),AOP(result)))
12657                         goto release;
12658
12659                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12660 #if 0
12661                 if (IS_PTR_CONST(rtype))
12662 #else
12663                 if (IS_CODEPTR(rtype))
12664 #endif
12665                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12666
12667 #if 0
12668                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12669 #else
12670                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12671 #endif
12672                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12673
12674 #if 0
12675                 if(AOP_TYPE(right) == AOP_IMMD) {
12676                   pCodeOp *pcop0, *pcop1, *pcop2;
12677                   symbol *sym = OP_SYMBOL( right );
12678
12679                         size = AOP_SIZE(result);
12680                         /* low */
12681                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12682                         /* high */
12683                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12684                         /* upper */
12685                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12686         
12687                         if (size == 3) {
12688                                 pic16_emitpcode(POC_MOVLW, pcop0);
12689                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12690                                 pic16_emitpcode(POC_MOVLW, pcop1);
12691                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12692                                 pic16_emitpcode(POC_MOVLW, pcop2);
12693                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12694                         } else
12695                         if (size == 2) {
12696                                 pic16_emitpcode(POC_MOVLW, pcop0);
12697                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12698                                 pic16_emitpcode(POC_MOVLW, pcop1);
12699                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12700                         } else {
12701                                 pic16_emitpcode(POC_MOVLW, pcop0);
12702                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12703                         }
12704                 } else
12705 #endif
12706                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12707                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12708                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12709                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12710                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12711                         if(AOP_SIZE(result) <2)
12712                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12713                 } else {
12714                         /* if they in different places then copy */
12715                         size = AOP_SIZE(result);
12716                         offset = 0 ;
12717                         while (size--) {
12718                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12719                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12720                                 offset++;
12721                         }
12722                 }
12723                 goto release;
12724         }
12725
12726         /* if the result is of type pointer */
12727         if (IS_PTR(ctype)) {
12728           int p_type;
12729           sym_link *type = operandType(right);
12730           sym_link *etype = getSpec(type);
12731
12732                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12733
12734                 /* pointer to generic pointer */
12735                 if (IS_GENPTR(ctype)) {
12736                   char *l = zero;
12737             
12738                         if (IS_PTR(type)) 
12739                                 p_type = DCL_TYPE(type);
12740                         else {
12741                 /* we have to go by the storage class */
12742                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12743
12744 /*              if (SPEC_OCLS(etype)->codesp )  */
12745 /*                  p_type = CPOINTER ;  */
12746 /*              else */
12747 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12748 /*                      p_type = FPOINTER ; */
12749 /*                  else */
12750 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12751 /*                          p_type = PPOINTER; */
12752 /*                      else */
12753 /*                          if (SPEC_OCLS(etype) == idata ) */
12754 /*                              p_type = IPOINTER ; */
12755 /*                          else */
12756 /*                              p_type = POINTER ; */
12757             }
12758                 
12759             /* the first two bytes are known */
12760       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12761             size = GPTRSIZE - 1; 
12762             offset = 0 ;
12763             while (size--) {
12764               if(offset < AOP_SIZE(right)) {
12765                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12766                 mov2f(AOP(result), AOP(right), offset);
12767 /*
12768                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12769                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12770                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12771                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12772                 } else { 
12773                   
12774                   pic16_aopPut(AOP(result),
12775                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12776                          offset);
12777                 }
12778 */
12779               } else 
12780                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12781               offset++;
12782             }
12783             /* the last byte depending on type */
12784             switch (p_type) {
12785             case IPOINTER:
12786             case POINTER:
12787                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12788                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12789 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12790                 break;
12791
12792             case CPOINTER:
12793                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12794                 break;
12795
12796             case FPOINTER:
12797               pic16_emitcode(";BUG!? ","%d",__LINE__);
12798                 l = one;
12799                 break;
12800             case PPOINTER:
12801               pic16_emitcode(";BUG!? ","%d",__LINE__);
12802                 l = "#0x03";
12803                 break;
12804
12805             case GPOINTER:
12806               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12807               break;
12808               
12809             default:
12810                 /* this should never happen */
12811                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12812                        "got unknown pointer type");
12813                 exit(1);
12814             }
12815             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12816             goto release ;
12817         }
12818         
12819         /* just copy the pointers */
12820         size = AOP_SIZE(result);
12821         offset = 0 ;
12822         while (size--) {
12823             pic16_aopPut(AOP(result),
12824                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12825                    offset);
12826             offset++;
12827         }
12828         goto release ;
12829     }
12830     
12831
12832
12833     /* so we now know that the size of destination is greater
12834     than the size of the source.
12835     Now, if the next iCode is an operator then we might be
12836     able to optimize the operation without performing a cast.
12837     */
12838     if(genMixedOperation(ic))
12839       goto release;
12840
12841     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12842     
12843     /* we move to result for the size of source */
12844     size = AOP_SIZE(right);
12845     offset = 0 ;
12846     while (size--) {
12847       mov2f(AOP(result), AOP(right), offset);
12848       offset++;
12849     }
12850
12851     /* now depending on the sign of the destination */
12852     size = AOP_SIZE(result) - AOP_SIZE(right);
12853     /* if unsigned or not an integral type */
12854     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12855       while (size--)
12856         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12857     } else {
12858       /* we need to extend the sign :( */
12859
12860       if(size == 1) {
12861         /* Save one instruction of casting char to int */
12862         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12863         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12864         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12865       } else {
12866         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12867
12868         if(offset)
12869           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12870         else
12871           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12872         
12873         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12874
12875         while (size--)
12876           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12877       }
12878     }
12879
12880 release:
12881     pic16_freeAsmop(right,NULL,ic,TRUE);
12882     pic16_freeAsmop(result,NULL,ic,TRUE);
12883
12884 }
12885
12886 /*-----------------------------------------------------------------*/
12887 /* genDjnz - generate decrement & jump if not zero instrucion      */
12888 /*-----------------------------------------------------------------*/
12889 static int genDjnz (iCode *ic, iCode *ifx)
12890 {
12891     symbol *lbl, *lbl1;
12892     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12893
12894     if (!ifx)
12895         return 0;
12896     
12897     /* if the if condition has a false label
12898        then we cannot save */
12899     if (IC_FALSE(ifx))
12900         return 0;
12901
12902     /* if the minus is not of the form 
12903        a = a - 1 */
12904     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12905         !IS_OP_LITERAL(IC_RIGHT(ic)))
12906         return 0;
12907
12908     if (operandLitValue(IC_RIGHT(ic)) != 1)
12909         return 0;
12910
12911     /* if the size of this greater than one then no
12912        saving */
12913     if (getSize(operandType(IC_RESULT(ic))) > 1)
12914         return 0;
12915
12916     /* otherwise we can save BIG */
12917     lbl = newiTempLabel(NULL);
12918     lbl1= newiTempLabel(NULL);
12919
12920     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12921     
12922     if (IS_AOP_PREG(IC_RESULT(ic))) {
12923         pic16_emitcode("dec","%s",
12924                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12925         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12926         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12927     } else {    
12928
12929
12930       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12931       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12932
12933       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12934       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12935
12936     }
12937     
12938     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12939     ifx->generated = 1;
12940     return 1;
12941 }
12942
12943 /*-----------------------------------------------------------------*/
12944 /* genReceive - generate code for a receive iCode                  */
12945 /*-----------------------------------------------------------------*/
12946 static void genReceive (iCode *ic)
12947 {    
12948
12949   FENTRY;
12950
12951 #if 0
12952   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12953         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12954 #endif
12955 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12956
12957   if (isOperandInFarSpace(IC_RESULT(ic))
12958       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12959           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12960
12961     int size = getSize(operandType(IC_RESULT(ic)));
12962     int offset =  pic16_fReturnSizePic - size;
12963
12964       assert( 0 );
12965       while (size--) {
12966         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12967                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12968                       offset++;
12969         }
12970
12971       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12972
12973       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12974       size = AOP_SIZE(IC_RESULT(ic));
12975       offset = 0;
12976       while (size--) {
12977         pic16_emitcode ("pop","acc");
12978         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12979       }
12980   } else {
12981     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12982     _G.accInUse++;
12983     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12984     _G.accInUse--;
12985
12986     /* set pseudo stack pointer to where it should be - dw*/
12987     GpsuedoStkPtr = ic->parmBytes;
12988
12989     /* setting GpsuedoStkPtr has side effects here: */
12990     assignResultValue(IC_RESULT(ic), 0);
12991   }
12992
12993   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12994 }
12995
12996 /*-----------------------------------------------------------------*/
12997 /* genDummyRead - generate code for dummy read of volatiles        */
12998 /*-----------------------------------------------------------------*/
12999 static void
13000 genDummyRead (iCode * ic)
13001 {
13002   pic16_emitcode ("; genDummyRead","");
13003   pic16_emitcode ("; not implemented","");
13004
13005   ic = ic;
13006 }
13007
13008 /*-----------------------------------------------------------------*/
13009 /* genpic16Code - generate code for pic16 based controllers        */
13010 /*-----------------------------------------------------------------*/
13011 /*
13012  * At this point, ralloc.c has gone through the iCode and attempted
13013  * to optimize in a way suitable for a PIC. Now we've got to generate
13014  * PIC instructions that correspond to the iCode.
13015  *
13016  * Once the instructions are generated, we'll pass through both the
13017  * peep hole optimizer and the pCode optimizer.
13018  *-----------------------------------------------------------------*/
13019
13020 void genpic16Code (iCode *lic)
13021 {
13022   iCode *ic;
13023   int cln = 0;
13024
13025     lineHead = lineCurr = NULL;
13026
13027     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13028     pic16_addpBlock(pb);
13029
13030 #if 0
13031     /* if debug information required */
13032     if (options.debug && currFunc) {
13033       if (currFunc) {
13034         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13035       }
13036     }
13037 #endif
13038
13039     for (ic = lic ; ic ; ic = ic->next ) {
13040
13041       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13042       if ( cln != ic->lineno ) {
13043         if ( options.debug ) {
13044           debugFile->writeCLine (ic);
13045         }
13046         
13047         if(!options.noCcodeInAsm) {
13048           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13049               printCLine(ic->filename, ic->lineno)));
13050         }
13051
13052         cln = ic->lineno ;
13053       }
13054         
13055       if(options.iCodeInAsm) {
13056         char *l;
13057
13058           /* insert here code to print iCode as comment */
13059           l = Safe_strdup(printILine(ic));
13060           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13061       }
13062         
13063       /* if the result is marked as
13064        * spilt and rematerializable or code for
13065        * this has already been generated then
13066        * do nothing */
13067       if (resultRemat(ic) || ic->generated ) 
13068         continue ;
13069         
13070       /* depending on the operation */
13071       switch (ic->op) {
13072         case '!' :
13073           pic16_genNot(ic);
13074           break;
13075             
13076         case '~' :
13077           pic16_genCpl(ic);
13078           break;
13079             
13080         case UNARYMINUS:
13081           genUminus (ic);
13082           break;
13083             
13084         case IPUSH:
13085           genIpush (ic);
13086           break;
13087             
13088         case IPOP:
13089           /* IPOP happens only when trying to restore a 
13090            * spilt live range, if there is an ifx statement
13091            * following this pop then the if statement might
13092            * be using some of the registers being popped which
13093            * would destroy the contents of the register so
13094            * we need to check for this condition and handle it */
13095            if (ic->next
13096              && ic->next->op == IFX
13097              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13098                genIfx (ic->next,ic);
13099           else
13100             genIpop (ic);
13101           break; 
13102             
13103         case CALL:
13104           genCall (ic);
13105           break;
13106             
13107         case PCALL:
13108           genPcall (ic);
13109           break;
13110             
13111         case FUNCTION:
13112           genFunction (ic);
13113           break;
13114             
13115         case ENDFUNCTION:
13116           genEndFunction (ic);
13117           break;
13118             
13119         case RETURN:
13120           genRet (ic);
13121           break;
13122             
13123         case LABEL:
13124           genLabel (ic);
13125           break;
13126             
13127         case GOTO:
13128           genGoto (ic);
13129           break;
13130             
13131         case '+' :
13132           pic16_genPlus (ic) ;
13133           break;
13134             
13135         case '-' :
13136           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13137             pic16_genMinus (ic);
13138           break;
13139
13140         case '*' :
13141           genMult (ic);
13142           break;
13143             
13144         case '/' :
13145           genDiv (ic) ;
13146           break;
13147             
13148         case '%' :
13149           genMod (ic);
13150           break;
13151             
13152         case '>' :
13153           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13154           break;
13155             
13156         case '<' :
13157           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13158           break;
13159             
13160         case LE_OP:
13161         case GE_OP:
13162         case NE_OP:
13163           /* note these two are xlated by algebraic equivalence
13164            * during parsing SDCC.y */
13165           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13166             "got '>=' or '<=' shouldn't have come here");
13167           break;
13168
13169         case EQ_OP:
13170           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13171           break;            
13172             
13173         case AND_OP:
13174           genAndOp (ic);
13175           break;
13176             
13177         case OR_OP:
13178           genOrOp (ic);
13179           break;
13180             
13181         case '^' :
13182           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13183           break;
13184             
13185         case '|' :
13186           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13187           break;
13188             
13189         case BITWISEAND:
13190           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13191           break;
13192             
13193         case INLINEASM:
13194           genInline (ic);
13195           break;
13196             
13197         case RRC:
13198           genRRC (ic);
13199           break;
13200             
13201         case RLC:
13202           genRLC (ic);
13203           break;
13204             
13205         case GETHBIT:
13206           genGetHbit (ic);
13207           break;
13208             
13209         case LEFT_OP:
13210           genLeftShift (ic);
13211           break;
13212             
13213         case RIGHT_OP:
13214           genRightShift (ic);
13215           break;
13216             
13217         case GET_VALUE_AT_ADDRESS:
13218           genPointerGet(ic);
13219           break;
13220             
13221         case '=' :
13222           if (POINTER_SET(ic))
13223             genPointerSet(ic);
13224           else
13225             genAssign(ic);
13226           break;
13227             
13228         case IFX:
13229           genIfx (ic,NULL);
13230           break;
13231             
13232         case ADDRESS_OF:
13233           genAddrOf (ic);
13234           break;
13235             
13236         case JUMPTABLE:
13237           genJumpTab (ic);
13238           break;
13239             
13240         case CAST:
13241           genCast (ic);
13242           break;
13243             
13244         case RECEIVE:
13245           genReceive(ic);
13246           break;
13247             
13248         case SEND:
13249           addSet(&_G.sendSet,ic);
13250           break;
13251
13252         case DUMMY_READ_VOLATILE:
13253           genDummyRead (ic);
13254           break;
13255
13256         default :
13257           ic = ic;
13258       }
13259     }
13260
13261
13262     /* now we are ready to call the
13263        peep hole optimizer */
13264     if (!options.nopeep)
13265       peepHole (&lineHead);
13266
13267     /* now do the actual printing */
13268     printLine (lineHead, codeOutFile);
13269
13270 #ifdef PCODE_DEBUG
13271     DFPRINTF((stderr,"printing pBlock\n\n"));
13272     pic16_printpBlock(stdout,pb);
13273 #endif
13274
13275     return;
13276 }
13277